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>
可以。select datetimefromparts(2018,3,25,0,0,0,0) at TIME ZONE 'E. Europe Standard Time'
select datetimefromparts(2018,3,26,0,0,0,0) at TIME ZONE 'E. Europe Standard Time'
。原因是什么?
答案 0 :(得分:15)
当type用作template argument(包括默认模板参数)时,不需要是完整类型。
类型模板参数的模板参数必须是type-id,可以命名不完整的类型:
因此对于f1
,默认模板参数为a<T>
,并且不必完整。鉴于f1<int>(1);
a<int>
不需要实例化。
但是,当您引用类模板的成员时,typename a<T>::type
的默认模板参数f2
,a<T>
必须是完整类型,然后导致implicit instantiation
当代码引用需要完全定义类型的上下文中的模板时,或者当类型的完整性影响代码,并且尚未显式实例化此特定类型时,将发生隐式实例化。例如,构造此类型的对象时,而不是构造指向此类型的指针时。
这适用于类模板的成员:除非在程序中使用该成员,否则它不会被实例化,也不需要定义。
所以给定f2<int>(1);
,a<int>
将被实例化,然后导致编译错误。