为什么在这种情况下构造类模板的成员函数?

时间:2013-06-04 16:42:55

标签: c++

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}

3 个答案:

答案 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关联的消息错误输出相同的消息。