默认模板参数的范围是什么?

What are the scopes of default template arguments?

标准 (§14.1) 模板参数说:

A template-parameter of a template template-parameter is permitted to have a default template-argument.

现在考虑以下代码:

#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().

这个声明

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();
}

C++ 标准的第 #14.1.14 段包含相应的示例

14 A template-parameter of a template template-parameter is permitted to have a default template-argument. When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter. [Example:

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 example]

想想如果没有 g() 的默认模板模板参数会发生什么:

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

格式错误,因为使用 C 需要在 g() 的定义中使用模板参数。现在您提供了 B 作为默认值,模板 g() 的定义格式正确,X 的模板模板参数的默认值无关紧要。

我认为这包含在 N4567 14.1/14

A template-parameter of a template template-parameter is permitted to have a default template-argument. When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-parameter. [Example:

    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 example]

因此模板模板参数的默认模板参数仅适用于声明默认参数的范围。
在示例中,它甚至在成员函数声明和成员函数定义之间切换模板模板参数的默认模板参数。