2016-07-24 86 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>; 
}; 

是否FooPack<Foo>::Container認爲,如果我們有Foo專業化被視爲是一回事嗎?那就是:

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!"); 

第二個斷言是否正確?預期的行爲是什麼?哎呀,我試圖做甚至是有效的?

我在三個編譯器上測試了它,並得到了不同的結果。看起來對於 MSVC和CLang,FooPack<Foo>::Container是不一樣的,但是GCC disagrees,這很酷,因爲那正是我想要的。

那麼,誰是對的? PS:我不確定我是否在標題上使用了正確的術語,也沒有在我的問題的正文中使用。建議和更正非常值得歡迎。

+0

我想模板特殊化是類型或值。這裏'Foo'是一個模板,既不是類型也不是值。 +1的問題。 – zahir

+5

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

+0

修改您的示例,使「IsFoo'的模板參數是一個類型名稱而不是模板,這使MSVC和GCC在原始示例上具有與GCC相同的輸出。 (見:http://coliru.stacked-crooked.com/a/f3052a75286f82e2)。 – jtedit

回答

1

14.5.7 Alias templates

1所述的模板聲明該聲明是別名聲明 (第7章)聲明所述標識符是一個別名模板。別名 模板是一個類型族的名稱。別名 模板的名稱是模板名稱。

2當模板id是指一個別名 模板的專業化,它相當於由 取代其模板參數爲模板參數 在別名的類型-ID獲得的相關類型模板。

在您的例子FooPack<Foo>::Container(無參數列表)是模板的名稱不表示一個類型,但只有一個模板。例如,Foo<int>Pack<Foo>::Container<int>將是template-id,因此將是等效的。

據我所知,該標準沒有指定模板名稱之間的任何等價關係,所以MSVC和Clang認爲只有相同的模板名稱是等價的。

但是,如果對於您的特定用例足夠了,您仍然可以根據模板標識進行特殊化或重載。例如: -

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>&) {}