プログラミング言語C++におけるconstexpr if文とstatic_assert宣言の組合せに関するメモ。
2023年2月会合にてstatic_assert(false)
を許容するP2593R1がCWG 2518へと統合され*1、C++言語仕様に対するDefect Reportとして遡及適用される。*2
CWG 2518適用前のC++言語仕様では、下記コードはプログラマの意図に反して関数テンプレートのインスタンス化より前にコンパイルエラーとなる。
#include <type_traits> template <typename T> T doubling(T x) { if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) { // 算術型の場合は2倍した値を返す return x * T{2}; } else { // それ以外の型はコンパイルエラー static_assert(false); // NG(CWG 2518適用前) // CWG 2518適用後は上記記述でOK } }
CWG 2518未適用C++コンパイラに対する回避策としては、static_assert宣言に「テンプレートパラメータに依存する(depends)が常にfalse
を返す」ヘルパ変数always_false_v<T>
などを経由した条件式を指定する。
#include <type_traits> template <typename T> constexpr bool always_false_v = false; template <typename T> T doubling(T x) { if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) { // 算術型の場合は2倍した値を返す return x * T{2}; } else { // それ以外の型はコンパイルエラー static_assert(always_false_v<T>); // OK } }
CWG 2518適用により、static_assert宣言の評価がインスタンス化タイミングに遅延される。オリジナルの提案文書P2593R1 §3.1より一部引用(下線部は強調)。
This sidesteps the question of whether it’s just
static_assert(false)
that should be okay orstatic_assert(0)
orstatic_assert(1 - 1)
orstatic_assert(not_quite_dependent_false)
. anything else. Just, allstatic_assert
declarations should be delayed until the template (or appropriate specialization or constexpr if substatement thereof) is actually instantiated.If the condition is false, we’re going to get a compiler error anyway. And that’s fine! But let’s just actually fail the program when it’s actually broken, and not early.
P2593R1 Allowing static_assert(false)
関連URL