C++11 static_assert条件部の定数式(constant expression)にて、標準ライブラリ提供のメタ関数を利用するときのメモ。
2017-11-10追記:一部のメタ関数で意図しないコンパイルエラーを引き起こすため、このイディオムを使うべきでない。C++1z(C++17)標準ライブラリで追加される変数テンプレート版メタ関数(std::is_same_v<T,U>
など)利用を推奨する。詳細は id:yohhoy:20171110 参照。
標準ヘッダ type_traits が提供するメタ関数を使うとき、下記2通りのいずれかで記述できる。後者の方が見やすい?
#include <type_traits> // is_sameメタ関数の利用例 static_assert( std::is_same<int, int>::value, "1" ); // OK static_assert( std::is_same<int, int>{}, "2" ); // OK
これらのメタ関数は、必ずstd::true_type
またはstd::false_type
から派生、つまりstd::integral_constant<bool, v>
からの公開派生クラスとなる。クラステンプレートintegral_constant
は「constexpr静的bool型定数メンバvalue」と「constexprなbool型への変換演算子」をもっているため、定数式が要求される場所では例示コードの記述が可能。N3337 20.9.3より引用(コードは簡略化している)。
namespace std { template <class T, T v> struct integral_constant { static constexpr T value = v; constexpr operator T() { return value; } }; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type; }
メモ:クラスintegral_constant
は条件を満たすためリテラル型(literal type)となる(3.9/p10)。{}
は同リテラル型に対するlist-initializationとなるため(8.5.4/p1)、integral_constant<〜>{}
は同クラス型のリテラル定数式(literal constant expression)として扱われる(5.19/p3)。このリテラル定数式に対してbool型への変換*1が働くことでconverted constant expressionとなり、これはliteral constant expressionでもあるため、最終的にbool型の定数式(constant expression)が得られる(5.19/p3)。おそらくは。
関連URL
- cppreference type_traits, cpprefjp type_traits
*1:ここでは "contextually converted to bool" が行われる。→id:yohhoy:20121110