Каковы масштабы аргументов шаблона по умолчанию?
В стандарте (§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()
.
Ответы
Ответ 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>
}
- конец примера]
Таким образом, параметр шаблона по умолчанию параметра шаблона шаблона применяется только в области, где объявлен параметр по умолчанию.
В примерах он даже переключает параметр шаблона по умолчанию для параметра шаблона шаблона между объявлением функции-члена и определением функции-члена.