struct ABC {};
template<typename T>
class DEF
{
void f0(typename T::ab) {} //ERROR
void f1() {typename T::ab var;} //Fine
};
DEF<ABC> obj;
我想如果我不使用类模板的特定成员函数,它永远不会被编译器构造。因此,即使使用f1()
也可以预期,代码编译得很好,因为obj
从不使用它。为什么f0()
的存在会导致编译错误?我也没有使用它。
{MinGW g ++ 4.7.2,Windows 7}
答案 0 :(得分:4)
每个成员函数声明是整个类定义的组成部分。同时,成员函数 definition 是一个完全独立的实体,它不是类定义的一部分。
当您实例化某个专用模板类的对象时,您将实例化该类的整个定义,即您正在“使用”该类的整个定义,这反过来意味着您正在“使用”所有成员声明同样。
一旦模板专用,下面是变成你的案例定义的部分
template<typename T>
class DEF
{
void f0(typename T::ab);
void f1();
};
以上所有内容必须对T
的给定值有效才能使类定义可用,即为了能够声明DEF<ABC> obj;
。
同时定义
template<typename T> void DEF<T>::f1()
{
typename T::ab var;
}
是一个独立的模板。只有在使用f1
时才会实例化。
答案 1 :(得分:2)
编译器至少需要一个有效的函数原型,然后确定它是否被使用(然后随后编译正文)。
答案 2 :(得分:2)
这是因为懒惰的实例化。当你DEF<ABC> obj
时。编译器将查看类DEF的原型/定义。因此void f0(typename T::ab)
失败,因为ab不存在而且您收到编译错误。
您没有为void f1(){typename T::ab var}
收到编译器错误的原因是因为它从未被实例化过。如果执行obj.f1()
,您将看到它将与与DEF :: f0关联的消息错误输出相同的消息。