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

时间:2016-11-25 20:58:34

标签: c++ templates c++14

标准(§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()

3 个答案:

答案 0 :(得分:7)

此声明

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允许模板模板参数的模板参数   有一个默认的模板参数。当这样的默认参数是   具体来说,它们适用于范围中的模板模板参数   模板模板参数。 [实施例:

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]

答案 1 :(得分:3)

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

template< template<typename T> class C>
void g() {
   C<>::f();
}
由于使用C需要g()定义中的模板参数,因此

会形成错误。现在你提供了B作为默认值,模板g()的定义很好,X的模板模板参数的默认值是无关紧要的。

答案 2 :(得分:1)

我认为N4567 14.1/14

涵盖了这一点
  

允许使用模板模板参数的模板参数   有一个默认的模板参数。当这样的默认参数是   如果指定,它们将应用于范围中的模板template-parameter   模板模板参数。 [例如:

colModel
  

- 结束示例]

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