问题 函数模板与未使用的模板参数


template<typename T>
struct a 
{ 
  using type = int;
  typename T::type i;
};

template<typename T, typename = a<T>>
void f1(T) {}

template<typename T, typename = typename a<T>::type>
void f2(T) {}

int main()
{
  f1<int>(1); // ok
  f2<int>(1); // error

  return 0;
}

实例化 a<int> 应该是一个错误,因为 int::type 是非法的。但似乎是这样 f1<int> 不能导致实例化 a<T>但是 f2<int> 能够。什么原因?


11190
2018-06-15 10:21


起源



答案:


当使用类型时 模板参数 (包括默认模板参数),不需要是完整类型。

类型模板参数的模板参数必须是type-id,可以命名不完整的类型:

因此对于 f1,默认模板参数是 a<T> 它不一定要完整。特定 f1<int>(1);  a<int> 不需要实例化。

但是当您引用类模板的成员时,作为默认模板参数 typename a<T>::type 的 f2a<T> 必须是完整的类型然后导致 隐式实例化

当代码引用需要完全定义类型的上下文中的模板时,或者当类型的完整性影响代码,并且此特定类型尚未显式实例化时,将发生隐式实例化。例如,构造此类型的对象时,而不是构造指向此类型的指针时。

这适用于类模板的成员:除非在程序中使用该成员,否则它不会实例化,也不需要定义。

所以给定 f2<int>(1);a<int> 将被实例化,然后导致编译错误。


15
2018-06-15 10:30