ISO C++标准 - 关于检查依赖基础的规则.为什么?

Joe*_*Joe 5 c++ templates standards-compliance visual-c++ visual-studio-2017

最近我偶然发现了VS 2017中的Visual C++编译器一致性模式切换.我读到了这个解释 ,其中给出了以下关于交换机如何禁止编译不符合代码的说明

template<typename T>
struct B {
    int f();
};

template<typename T>
struct D : B<T> {
    int g();
};

template<typename T>
int D<T>::g() {
    return f();  // error: should be ‘this->f()’
}
Run Code Online (Sandbox Code Playgroud)

在D :: g的定义中,符号f来自依赖基类B,但标准C++ 在查找满足f的使用的声明时不允许检查依赖基类.这是Visual C++长期以来无法诊断的源代码中的错误.

好的,很好,我明白了.除了一件事.为什么?

为什么标准容许检查对于f依赖基类()?这项禁令的理由是什么?标准是否给出了一个?

如果B和D都只是常规的非模板结构,则f()将被正确地解释为对基类(er ... base struct)成员函数的调用.那么为什么当它们是模板时却没有这样做呢?

(我确信这是一个很好的理由但是目前我的理解有限,这似乎是一种烦恼.我确实尝试搜索这个并找到至少一个关于它的问题,但没有关于它的"为什么")

son*_*yao 5

因为模板可能稍后专门化.例如

template<typename T>
struct B {
    int f();
};

template<typename T>
struct D : B<T> {
    int g();
};

template<typename T>
int D<T>::g() {
    return f();  // the name f won't be looked up when not knowing the exact type of T
}

template<>
struct B<int> {
    // no function named f for B<int>
};
Run Code Online (Sandbox Code Playgroud)

因此,标准C++表示非依赖名称不会在依赖基类中查找.

添加this->使名称依赖和依赖名称只能在实例化时查找,并且在那时必须知道必须探索的确切基本特化.

另请参阅两阶段查找.

  • @Joe - 非成员“f()”的存在会使查找变得复杂。它应该用于“B&lt;int&gt;”,还是缺少的成员函数应该是一个错误?如果你必须说“this-&gt;f()”,编译器就会知道。 (2认同)