2016-07-24 10 views
19

我々はテンプレートの別名と専門

template<typename T> 
struct Foo 
{ 
}; 

template<typename T> 
struct Bar 
{ 
}; 

template< template<typename T> class C > 
struct Pack 
{ 
    template<typename T> 
    using Container = C<T>; 
}; 

を持っていると仮定すると、我々はFooのための専門を持っている場合は同じものとして扱われることをFooPack<Foo>::Containerを想定していますか?つまり、

template< template<typename T> class C > 
struct IsFoo : std::false_type 
{ 
}; 

template<> 
struct IsFoo<Foo> : std::true_type 
{ 
}; 

static_assert(IsFoo<Foo>::value,        "Only foos!"); 
static_assert(IsFoo< Pack<Foo>::Container >::value,   "Only foos!"); // ??? 
static_assert(IsFoo< Pack<Bar>::Container >::value == false, "Not a foo!"); 

この2番目のアサーションは正しいですか?期待される行動は何ですか?ヘック、私も有効にしようとしているものですか?

私は3つのコンパイラでそれをテストしましたが、私は異なる結果を得ました。 MSVCとCLangについては、FooPack<Foo>::Containerは同じものではないと思われますが、これはまさに私が望んでいたので、涼しいです。GCC disagrees

だから、誰が正しいですか?

PS:タイトルや質問の本文に正しい用語を使用しているかどうかはわかりません。提案や訂正は大歓迎です。宣言がエイリアス宣言 (条項7)である

+0

私はテンプレートの特殊化は、タイプまたは値のためであると思いました。ここで 'Foo'は型でも値でもないテンプレートです。 +1の質問です。 – zahir

+5

[CWG1286](http://wg21.link/cwg1286)。 – cpplearner

+0

'IsFoo'のテンプレートパラメータがテンプレートではなくtypenameであるようにサンプルを変更すると、MSVCとGCCの両方が元の例のGCCと同じ出力になります。 (http://coliru.stacked-crooked.com/a/f3052a75286f82e2参照)。 – jtedit

答えて

1

14.5.7 Alias templates

1テンプレート宣言は、識別子がエイリアステンプレートであることを宣言する。エイリアス テンプレートは、ファミリタイプの名前です。別名 テンプレートの名前はテンプレート名です。

2テンプレートIDはエイリアス テンプレートの特殊化を指す場合、それはエイリアスのタイプIDでテンプレートパラメータ ためそのテンプレート引数の 置換することにより得られた関連するタイプと同等ですテンプレート。あなたの例FooPack<Foo>::Container(なしパラメータリスト)で

はタイプだけのテンプレートを示すものではありませんテンプレート名です。例えば、Foo<int>Pack<Foo>::Container<int>はテンプレートIDであるため、同等です。

私の知るところでは、この標準ではテンプレート名の間に等価関係が指定されていないので、MSVCとClangは同じテンプレート名のみが同等であると想定するのは当然です。

しかし、特定のユースケースで十分であれば、template-idに基づいて特殊化またはオーバーロードすることができます。例えば:

template< typename C > 
struct IsFoo : std::false_type 
{ 
}; 

template<class T> 
struct IsFoo<Foo<T>> : std::true_type 
{ 
}; 

static_assert(IsFoo<Foo<int>>::value,        "Only foos!"); 
static_assert(IsFoo< Pack<Foo>::Container<int> >::value,   "Only foos!"); 
static_assert(IsFoo< Pack<Bar>::Container<int> >::value == false, "Not a foo!"); 

または

template<class T> 
void do_stuff(const T&) {} 

template<class T> 
void do_stuff(const Foo<T>&) {} 
関連する問題