yohhoyの日記

2017-11-10

真偽値を返すメタ関数利用上の注意

C++標準ライブラリ<type_traits>ヘッダ提供の真偽値を返すメタ関数において、is_xxx<T>{} のような真偽値アクセス(→id:yohhoy:20121207)は適切でない。素直に is_xxx<T>::value で真偽値を取り出すか、C++1zで追加される変数テンプレート版メタ関数 is_xxx_v<T> を利用すべき。

C++1z(C++17)標準ライブラリ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による意図しないコンパイルエラーを引き起こす。

ノート:APIユーザにconjunction, disjunctionメタ関数を直接公開せず、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

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/yohhoy/20171110/p1