2016-07-24 34 views
19

Zakładając mamySzablon alias i specjalizacja

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>; 
}; 

Czy Foo i Pack<Foo>::Container powinien być traktowany jako samo jeśli mamy specjalizacji dla Foo? To znaczy:

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

Czy to drugie twierdzenie jest poprawne? Jakie jest oczekiwane zachowanie? Heck, czy to, co próbuję zrobić, nawet ważne?

Przetestowałem to na trzech kompilatorach i uzyskałem inne wyniki. Wygląda na to, że dla MSVC i CLang, Foo i Pack<Foo>::Container to nie to samo, ale GCC disagrees, co jest fajne, ponieważ dokładnie to chciałem.

Kto ma rację?

PS: Nie jestem pewien, czy używam poprawnej terminologii na tytule, ani w treści mojego pytania. Sugestie i poprawki są mile widziane.

+0

Myślałem szablon specjalizacji jest dla typów lub wartości. Tutaj 'Foo' jest szablonem, ani typem ani wartością. +1 dla pytania. – zahir

+5

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

+0

Modyfikowanie przykładu tak, że parametr szablonu 'IsFoo' jest typem, a nie szablonem powoduje, że zarówno MSVC, jak i GCC mają takie same wyniki jak dla GCC na oryginalnym przykładzie. (patrz: http://coliru.stacked-crooked.com/a/f3052a75286f82e2). – jtedit

Odpowiedz

1

14.5.7 Alias templates

1 Wzór deklaracja w której zgłoszenie to alias deklaracja (Rozdział 7) deklaruje identyfikator się szablon aliasu. Szablon aliasu to nazwa rodziny typów. Nazwa szablonu aliasu jest nazwą szablonu.

2 gdy szablon ID odnosi się do specyfikacji aliasu matrycy, jest to równoważne ze skojarzonym typem otrzymanej zastąpienie jej szablonu-argumentów szablonu-parametry w typu ID alias szablon.

W przykładzie Foo i Pack<Foo>::Container (lista parametrów) nie są template-nazwy, które nie reprezentują typ ale tylko szablon. Na przykład Foo<int> i Pack<Foo>::Container<int> byłyby szablonami i dlatego byłyby równoważne.

Zgodnie z moją wiedzą standard nie określa żadnej relacji równoważności między nazwami szablonów, więc MSVC i Clang mają rację, zakładając, że tylko identyczne nazwy szablonów są równoważne.

Ale nadal możesz specjalizować się lub przeciążać w oparciu o identyfikator szablonu, jeśli jest to wystarczające dla konkretnego przypadku użycia. np .:

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

lub

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

template<class T> 
void do_stuff(const Foo<T>&) {} 
Powiązane problemy