私はウォルターブラウンがCppcon14で最新のテンプレートプログラミング(パートI、パートII)について語った彼のvoid_t
SFINAEテクニックのプレゼンテーションを見ました。
例:すべてのテンプレート引数が正しい形式であるかどうか
を評価する単純な変数テンプレートvoid
があるとします。
template< class ... > using void_t = void;
そして、memberと呼ばれるメンバー変数の存在をチェックする次の特性:
template< class , class = void >
struct has_member : std::false_type
{ };
// specialized as has_member< T , void > or discarded (sfinae)
template< class T >
struct has_member< T , void_t< decltype( T::member ) > > : std::true_type
{ };
これがなぜ、どのように機能するかを理解しようとしました。したがって、小さな例:
class A {
public:
int member;
};
class B {
};
static_assert( has_member< A >::value , "A" );
static_assert( has_member< B >::value , "B" );
1。 has_member< A >
has_member< A , void_t< decltype( A::member ) > >
A::member
存在するdecltype( A::member )
整形式ですvoid_t<>
有効であり、次のように評価されますvoid
has_member< A , void >
したがって、専用のテンプレートを選択しますhas_member< T , void >
と評価するtrue_type
2。 has_member< B >
has_member< B , void_t< decltype( B::member ) > >
B::member
存在しませんdecltype( B::member )
不正な形式であり、黙って失敗する(sfinae)has_member< B , expression-sfinae >
このテンプレートは破棄されます
- コンパイラは
has_member< B , class = void >
デフォルト引数としてvoidを見つけます has_member< B >
評価するfalse_type
質問:
1.これに対する私の理解は正しいですか?
2. Walter Brownは、デフォルトの引数はvoid_t
、それが機能するために使用されるものとまったく同じ型でなければならないと述べています。何故ですか?(このタイプが一致する必要がある理由がわかりません。デフォルトのタイプだけではうまくいきませんか?)
has_member< T , class = void >
デフォルトをする必要性をvoid
まだ見ていません。このトレイトが常に1つのテンプレート引数でのみ使用されると仮定すると、デフォルトの引数はどのタイプでもかまいません。
template <class, class = void>
ことに注意してくださいtemplate <class, class = void_t<>>
。そのため、void_t
エイリアステンプレートの実装を使用して、私たちは何でも自由に実行できます:)
has_member<A,int>::value
。次に、評価される部分的な特殊化has_member<A,void>
は一致しません。したがって、それはである必要がありますhas_member<A,void>::value
。または、構文糖衣では、typeのデフォルト引数である必要がありますvoid
。