VisualStudio错误或C++标准已更改?
#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;
}
当我使用 c++ 17 或 11 时,这段代码就可以了。但是当我将 c++ 标准设置为 20 时,发生的 C3816 错误说找不到 hello 函数,我对原因感到困惑,为什么这个错误直到 c++ 20 才会出现。
回答
该hello();语句不依赖于模板参数,并且在直接搜索上下文中没有这样的名称(即内部ttt或其非模板基类,如果有的话),因此名称查找将在非模板上下文中完成。即,如果您有一个名为 的全局函数hello,则会改为选择它。这是由每个标准规定的,至少从 C++11 开始。一种符合标准的方法是使纯右值依赖于模板的参数:
this->hello(); // this is dependant on T
另一种方法是使用带有base<ttt<T>>::前缀的完全限定名称,但这意味着只能选择该版本的函数。如果ttt将覆盖它,如果继承树将扩展并且将存在另一个重载覆盖hello,如果将存在多个虚拟继承,则此类限定名称可能指向非预期的函数成员。
Visual Studio 中的错误至少可以追溯到 VS2010,我个人多年来一直受到它的困扰,因为开发人员会编写使用 MSVC 编译的代码,但不会被 gcc 编译,我每次都必须向他们解释什么是错的( “但它可以编译!”)。
- @RobertAndrzejuk: The standard behavior is **superior** in that it avoids having a function call that looks like a call to a free function actually call a member function (or else changing the normal shadowing rules if you prefer the free function). Failing to implement that was definitely a bug (if an understandable one given the vintage of the compiler).