C++標準ライブラリ <type_traits> ヘッダ提供の真偽値を返すメタ関数において、is_xxx<T>{}
のような真偽値変換(→id:yohhoy:20121207)は適切でないケースがある。素直にis_xxx<T>::value
で真偽値を取り出すか、C++1z(C++17)で追加される変数テンプレート版メタ関数is_xxx_v<T>
の利用が望ましい。
C++1z標準ライブラリconjunction
, disjunction
メタ関数ではインスタンス化の短絡評価をサポートするが、is_xxx<T>{}
方式では期待通りに短絡評価が機能しなくなる。例示として id:yohhoy:20171103 サンプルコードを引用。
// C++1z(C++17) #include <atomic> #include <type_traits> template <typename T> struct is_lock_free_impl : std::bool_constant<std::atomic<T>::is_always_lock_free> { }; template <typename T> using is_lock_free = std::conjunction<std::is_trivially_copyable<T>, is_lock_free_impl<T>>; // 非Trivially Copyableなクラス型X struct X { ~X() {} }; static_assert( !is_lock_free<X>::value, "X is not lock-free" ); // OK static_assert( !is_lock_free<X>{}, "X is not lock-free" ); // NG: ill-formed
is_lock_free<X>{}
はstd::conjunction<B...>
型のインスタンス化を要求するため、本来は短絡評価でスキップされるべきis_lock_free_impl<X>
型のインスタンス化を要求してしまい、ill-formedによる意図しないコンパイルエラーを引き起こす。
ノート:conjunction
, disjunction
メタ関数を直接公開(alias template)せず、std::bool_constant
でラップすれば問題を回避することは一応可能。
template <typename T> struct is_lock_free : std::bool_constant< std::conjunction_v<std::is_trivially_copyable<T>, is_lock_free_impl<T>> > { }; static_assert( !is_lock_free<X>::value, "X is not lock-free" ); // OK static_assert( !is_lock_free<X>{}, "X is not lock-free" ); // OK