2016-11-30 19 views
21

Rozważmy C++ 11 program:Dziwne zachowanie domyślnego szablonu-argumentu w szablonie-template-parametru

#include <iostream> 

template <class A, class B = char> struct Cont { 
    Cont() { std::cout << sizeof(B); } 
}; 

template <template<class, class = int> class C, class E> class Wrap1 
{ 
    C<E> ce; 
}; 

template <template<class, class = int> class C, class... E> class Wrap2 
{ 
    C<E...> ce; 
}; 

int main() 
{ 
    Wrap1<Cont, void> w1; 
    Wrap2<Cont, void> w2; 
} 

Kiedy skompilowany albo z gcc lub brzękiem, wyjście jest 41.

Czy to zachowanie jest zgodne z normą? Gdzie dokładnie określa to standard (zarówno dla Wrap1 i Wrap2)? To jest częściowo zainspirowane przez this other question.

+2

ICC i MSVC generuje '44'. Pójdę z bugiem. –

+0

Załóżmy, że jest to specyficzna implementacja kompilatora. –

Odpowiedz

1

W klasie Wrap2 pakiet parametrów "class ... E" zastąpi wszystkie parametry określone przez "class C" (w tym domyślny parametr "int"), więc "Wrap2 w2" zwróci 1, który jest domyślny parametr struktury Cont.

Pakiet parametrów zastąpił wszystkie parametry klasy C, więc domyślne parametry C nie działały tutaj.

#include <iostream> 
#include <typeinfo> 

template <class A=char, class B = short, class C = int> struct MyTest 
{ 
    MyTest() 
    { 
     std::cout << sizeof(A) << " " << typeid(A).name() << " "; 
     std::cout << sizeof(B) << " " << typeid(B).name() << " "; 
     std::cout << sizeof(C) << " " << typeid(C).name() << std::endl; 
    } 
}; 

template <template<class = double, class = double, class = double> class D, class E, class... F> class Wrap 
{ 
    D<E> de; // the parameters of D is: E + default parameters of D. 
    D<F...> df; // the parameters of D is: F... + default parameters of MyTest, the default parameter of D don't work, it will be replaced by pack F. 
}; 

int main() 
{ 
    Wrap<MyTest, int, int> w; 
} 

//g++ 5.4.0 
//output: 
//4 i 8 d 8 d 
//4 i 2 s 4 i 
+0

Widzę, co się dzieje, pytam, gdzie w normie zdefiniowano to zachowanie. –