Visual Studio 错误或 C++ 标准已更改?

deg*_*ong 1 c++ c++20 visual-studio-2017 visual-studio-2019

#include <iostream>

template<typename T>
struct base {
    void hello() {
    }
};

template<typename T>
struct ttt : public base<ttt<T>> {
public:
    ttt() {
        hello();
    }
};

int main() {
    ttt<int> t();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我使用 c++ 17 或 11 时,这段代码就可以了。但是当我将 c++ 标准设置为 20 时,发生的 C3816 错误说找不到 hello 函数,我对原因感到困惑,为什么这个错误直到 c++ 20 才会出现。

Swi*_*Pie 5

hello();语句不依赖于模板参数,并且在直接搜索上下文中没有这样的名称(即内部ttt或其非模板基类,如果有的话),因此名称查找将在非模板上下文中完成。即,如果您有一个名为 的全局函数hello,则会改为选择它。这是由每个标准规定的,至少从 C++11 开始。一种符合标准的方法是使纯右值依赖于模板的参数:

     this->hello();  // this is dependant on T
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用带有base<ttt<T>>::前缀的完全限定名称,但这意味着只能选择该版本的函数。如果ttt将覆盖它,如果继承树将扩展并且将存在另一个重载\覆盖hello,如果将存在多个虚拟继承,则此类限定名称可能指向非预期的函数成员。

Visual Studio 中的错误至少可以追溯到 VS2010,我个人多年来一直受到它的困扰,因为开发人员会编写使用 MSVC 编译的代码,但不会被 gcc 编译,我每次都必须向他们解释什么是错的( “但它可以编译!”)。

  • @RobertAndrzejuk:标准行为是**优越的**,因为它避免了看起来像调用自由函数的函数调用实际上调用了成员函数(或者如果您更喜欢自由函数,则更改正常的隐藏规则)。未能实现这绝对是一个错误(如果考虑到编译器的年份,这是可以理解的)。 (2认同)