2013-08-11 25 views
10

Poniższy kodCzęściowa specjalizacja dla zmiennej liczbie argumentów szablonu musi pierwszy niekomunistyczny o zmiennej liczbie argumentów parametr szablonu

#include <iostream> 
#include <utility> 

template<typename F, typename... T> 
struct Wrapper{ }; 

template<typename T> 
struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 

int main() 
{ 
    Wrapper<int, double> w; 

    std::cout << is_wrapper<decltype(w)>::value << std::endl; 
} 

drukuje 0. Jeśli jednak uncomments dwie linie w środku drukuje 1.

Dlaczego nie robi” t zawsze drukuje 1? Czy druga specjalizacja częściowa nie powinna obejmować również przypadku, który najwyraźniej obejmuje tylko trzecia (skomentowana) specjalizacja częściowa?

Odpowiedz

1

Kod powinien rzeczywiście pasować do specjalizacji częściowej; Standard nigdy nie zabraniał tego, ale kompilatory potrzebowały trochę czasu, aby poprawnie zaimplementować szablony variadyczne i ich dedukcję. GCC jest zgodny od wersji 4.9.0 i Clang od wersji 3.6. Odpowiedni raport błędu dla Clanga to #22191 (nie mogę jednak znaleźć GCC).

0

Zwykle podczas pisania szablonów, które byłyby wyspecjalizowane, najpierw używam zgłoszenia do przodu i deklaruję, że przypadki należą do specjalizacji. W twoim przypadku rozumiem, że próbujesz napisać szablon wariasu bez pustego przypadku (to znaczy szablon wariasu, który może mieć co najmniej jeden typ).

Twój kod zaskoczył mnie, ponieważ uważam, że masz rację, pełna specjalizacja variadyczna twojej cechy pasuje do przypadków dziury ... Najpierw próbowałem użyć deklaracji z wyprzedzeniem twojej klasy cech i zdefiniować TYLKO pełną wariancję specjalizacja (więc jeśli parametr cechy nie jest instancją Wrapper, kompilacja kończy się niepowodzeniem). I to dokładnie to, co ocurred, rozczarowujące mnie znowu:

#include <iostream> 
#include <utility> 

template<typename F , typename... T> 
struct Wrapper {}; 

template<typename T> 
struct is_wrapper; 

//template<typename T> 
//struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 

using my_wrapper_type = Wrapper<int,double>; 

int main() 
{ 
    std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl; 
}//"Invalid use of incomplete type" ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Wreszcie próbowałem z przodu deklaracji metody w klasie Wrapper. I zaskakująco, to działa:

#include <iostream> 
#include <utility> 

template<typename... T> 
struct Wrapper; 

template<typename F, typename... T> 
struct Wrapper<F,T...>{ }; 


template<typename T> 
struct is_wrapper : std::false_type {}; 

template<typename... T> 
struct is_wrapper<Wrapper<T...>> : std::true_type {}; 

//template<typename F, typename... T> 
//struct is_wrapper<Wrapper<F, T...>> : std::true_type {}; 


using my_wrapper_type = Wrapper<int,double>; 

int main() 
{ 
    std::cout << std::boolalpha << is_wrapper<my_wrapper_type>::value << std::endl; 
} 

Drukuje:

prawdziwymi

Here jest kod uruchomiony w ideone.

Pozdrawiam, nie rozumiem, dlaczego Twój kod nie działa, a mój działa. To jest błąd kompilatora, czy jest coś, czego nam brakuje? Nie wiem.

+0

Różnica polega na liczbie parametrów szablonu dla szablonu klasy "Wrapper". Twoja (druga) wersja ma tylko jeden parametr szablonu, podczas gdy wersja OP ma dwa parametry. Twoja częściowa specjalizacja 'struct Wrapper ' nie zmienia tego. – dyp

+0

@DyP OK, ale jeśli masz szablon z dwoma parametrami (Jeden normalny parametr szablonu i parametr szablonu variadic) i przekazujesz pakiet variadic do tego szablonu, pakiet variadic nie musi się rozszerzać, dopasowując pierwszy normalny parametr, i drugi parametr (parametr variadic)?Tego właśnie nie rozumiem, dlaczego opakowanie nie jest w ten sposób rozszerzane. – Manu343726

+0

Nadal próbuję dowiedzieć się, gdzie (i dlaczego) Standard zabrania częściowej specjalizacji, aby dopasować pakiet parametrów w tym przypadku. Zgadnij, że jest gdzieś w okolicy [temp.deduct.type]/9. (Rozszerzenie paczki różni się od dedukowania.) – dyp

0

Jeśli dobrze rozumiem twój problem to tylko priorytet specjalizacja,

is_wrapper<decltype(w)> 

Może być specjalizuje przez 2 Szablon:

template<typename T> // exact specialization 
template<typename... T> // variadic specialization with one parameter 

W tym przypadku kompilator wybrać w pierwszej kolejności dokładnie specjalizacji i tak szablonu nigdy nie jest instatiate w tobie.

+0

To jest niepoprawne. Częściowe specjalizacje są zawsze preferowane do szablonów podstawowych (i tak czy inaczej muszą być bardziej wyspecjalizowane), patrz §14.5.5.1. – Columbo

Powiązane problemy