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 才会出现。
该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 编译,我每次都必须向他们解释什么是错的( “但它可以编译!”)。