为什么编译器会忽略模板类中的struct元素?

时间:2014-06-04 13:34:18

标签: c++ templates compiler-construction struct

我正在使用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()时,编译器才会显示错误。那是为什么?

2 个答案:

答案 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}}如果该提案得到标准化的话。)