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

Why does the compiler ignore struct elements inside a template class?

本文关键字:struct 元素 编译器 为什么      更新时间:2023-10-16

我正在使用g++编译器。我编写了以下代码,其中包含一个模板类定义。类有一个叫做node的结构数据类型,它的元素a和b都是泛型类型。该类有一个名为print的函数,它打印p.h,其中p是类对象的节点类型的变量。编译器没有显示任何错误,尽管'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);
    }

只有当m.p rprint()在main中没有注释时,编译器才会显示错误。为什么呢?

如果不使用模板的对象(实例),编译器只检查模板的逻辑。模板将不会被实例化。但是,如果您尝试使用模板的实例,该模板将被实例化(扩展),那么您将看到错误,h不是p的成员。

也就是说,如果你注释掉//m.print(),模板将被实例化

为了使编写template类更容易一点,未调用的template方法不会实例化。

检查一些事情——方法的签名,查找只涉及不依赖于类的template参数的数据的任何方法或函数等。

在这种情况下,p在技术上依赖于类的template参数,因此检查p.h是否有效是在实例化时完成的。现在,您可以证明没有e使得p.h是有效的,但是编译器不必这样做,所以它没有麻烦。

程序可能仍然是病态的:如果没有template的有效专门化,标准中有条款规定程序可能是病态的(不需要诊断),但我不知道这是否适用于template的方法。

一旦调用了print,方法就会被实例化,错误就会被注意到。

std库中使用这个方法的一个例子是vector——它的一些方法,包括<,在它的数据上盲调用<vector不要求它的数据支持<,但如果有人试图调用<,它确实需要它。

在这种情况下,现代c++技术将涉及禁用vector::operator<(标准讨论"不参与重载解析"),而在c++ 1z中,通过requires子句(如果该提案被标准化),这变得容易得多。