我的程序在 Visual Studio 的 C++20 模式下表现符合预期,但我需要让它在 C++17 模式下运行,在该模式下程序会改变其输出。
最小化后,它看起来如下:
template <typename T>
int f() { return g(T{}); }
namespace {
struct A{
friend int g(const A &) { return 1; }
};
}
template <typename T>
int g(T&&) { return 2; }
int main() { return f<A>(); }
在 C++20 模式下输出为main()
,1
而在 C++17 模式下输出为2
。在线演示: https: //gcc.godbolt.org/z/h8b8qoGGj
我想知道 C++20 的哪个新特性(C++17 中没有)导致了结果的差异。
它与 C++17 与 C++20 无关。
模板中的 MSVC 默认名称查找行为不符合标准。您需要给出标志
/permissive-
以使其符合标准。标志
/std:c++20
(或任何/std:c++*
用于较新 C++ 修订版的标志)/permissive-
也隐式设置,而/std:c++17
早期修订版的和标志则没有。在标准 C++ 中,结果
1
始终是唯一正确的答案。 的第二个重载g
无法通过对 的调用的常规非限定查找找到,f
因为该查找是从 的f
定义点执行的,而该位置尚未声明重载。 它也无法通过 ADL 找到,因为它没有放在与 相同的命名空间中A
。