我正在使用g ++编译器。我编写了以下代码,其中包含模板类定义。该类有一个名为node的struct数据类型,它包含泛型类型的元素a和b。该类有一个名为print的函数,它打印p.h,其中p是类对象的类型node的变量。编译器没有显示任何错误,尽管' h'不是struct node的元素。那是为什么?
#include<iostream>
#include<cstdlib>
using namespace std;
template <typename e>
class mc
{
typedef struct node
{
e a,b;
}node;
node p;
public:
void print();
};
template <typename e>
void mc<e>::print()
{
std::cout<<p.h;
}
int main()
{
mc<int> m;
//m.print();
return(0);
}
只有在main中取消注释m.print()时,编译器才会显示错误。那是为什么?
答案 0 :(得分:1)
如果您不使用模板的对象(实例),编译器只会检查模板的逻辑。模板不会被实例化。但是,如果您尝试使用模板的实例,该模板将被实例化(展开),那么您将看到h
不是p
成员的错误。
也就是说,如果你注释掉//m.print()
,模板就会被实例化。
答案 1 :(得分:0)
为了使template
类更容易编写,未实例化非调用template
方法。
检查了一些东西 - 方法的签名,它查找任何只涉及不依赖于类的template
参数的数据等的方法或函数。
在这种情况下,p
在技术上依赖于类的template
参数,因此p.h
有效的检查是在实例化时完成的。现在,您可以证明没有e
使p.h
有效,但编译器没有,所以它不会打扰。
该程序可能仍然格式不正确:如果template
没有有效的专业化,标准中有条款可能格式不正确(无需诊断),但我不知道是否这适用于template
的方法。
调用print
后,将实例化该方法,并注意到错误。
在std
库中使用它的示例是vector
- 其中的一些方法,包括<
,对其数据进行盲调用<
。 vector
并不要求其数据支持<
,但如果有人试图调用<
,则确实需要它。
现代C ++技术将涉及在这种情况下禁用vector::operator<
(标准谈到“不参与重载决策”),而在C ++ 1z中,通过requires
子句变得容易得多({1}}如果该提案得到标准化的话。)