Стандартные (§14.1) параметры шаблона говорят:

Параметр-шаблон шаблона-параметра-шаблона может иметь аргумент-шаблон по умолчанию.

Теперь рассмотрим следующий код:

#include <iostream>

using namespace std;

struct A {};
struct B {};

template<typename T = A>
struct X;

template<>
struct X<A> {
   static void f() { cout << 1 << endl; }
};

template<>
struct X<B> {
   static void f() { cout << 2 << endl; }
};

template< template<typename T = B> class C>
void g() {
   C<>::f();
}

int main() {
   g<X>();
}

Это вывод:

вывод: 2

В этом случае параметр шаблона шаблона - C.
Но я не понимаю, почему C<B>::f() вызывается внутри g().

18
Adib 25 Ноя 2016 в 23:58

3 ответа

Лучший ответ

Эта декларация

template< template<typename T = B> class C>
void g() {
   C<>::f();
}

Эквивалентно

template< template<typename T = B> class C>
void g() {
   C<B>::f();
}

Таким образом, этот призыв

   g<X>();

Эквивалентно вызову функции

void g() {
   X<B>::f();
}

Параграф 14.1.14 стандарта C ++ содержит соответствующие примеры.

14 Параметр-шаблон шаблона-параметра-шаблона разрешается иметь аргумент-шаблон по умолчанию. Когда такие аргументы по умолчанию указаны, они применяются к параметру шаблона шаблона в области действия параметра шаблона шаблона. [Пример:

template <class T = float> struct B {}; 
template <template <class TT = float> class T> struct A {
 inline void f();
 inline void g(); 
}; 
template <template <class TT> class T> void A<T>::f() {
 T<> t; // error - TT has no default template argument 
} 
template <template <class TT = char> class T> void A<T>::g() {
 T<> t; // OK - T<char> 
} 

—Конечный пример]

7
Vlad from Moscow 25 Ноя 2016 в 22:10

Подумайте, что произошло бы без параметра шаблона по умолчанию для g ():

template< template<typename T> class C>
void g() {
   C<>::f();
}

Было бы неправильно сформировано, так как использование C потребовало бы параметра шаблона внутри определения g (). Теперь, когда вы указали B по умолчанию, определение шаблона g () правильно сформировано, и значение по умолчанию для параметра шаблона шаблона X не имеет значения.

3
Maarten Hilferink 25 Ноя 2016 в 21:41

Я думаю, что это покрывается N4567 14,1 / 14

Параметр-шаблон шаблона-параметра-шаблона может иметь аргумент-шаблон по умолчанию. Когда такие аргументы по умолчанию указаны, они применяются к параметру шаблона шаблона в области действия параметра шаблона шаблона. [Пример:

    template <class T = float> struct B {}; 

    template <template <class TT = float> class T>
    struct A { inline void f(); inline void g(); };

    template <template> <class TT> class T> void A<T>::f() {
      T<> t; // error - TT has no default template argument
    }

    template <template <class TT = char> class> T> void A<T>::g() {
      T<> t; // OK - T<char>
    }

- конец примера]

Таким образом, параметр шаблона по умолчанию для параметра шаблона шаблона применяется только в области, в которой объявлен параметр по умолчанию.
В примерах он даже переключает параметр шаблона по умолчанию для параметра шаблона шаблона между объявлением функции-члена и определением функции-члена.

1
SirGuy 25 Ноя 2016 в 21:45