Подтвердить что ты не робот

Каковы масштабы аргументов шаблона по умолчанию?

В стандарте (§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>();
}

На выходе:

out put: 2

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

4b9b3361

Ответ 1

Это объявление

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 Стандарта С++ содержит соответствующие примеры

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

-end пример]

Ответ 2

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

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

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

Ответ 3

Я думаю, что это покрывается 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>
    }

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

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