该函数调用是否应该模棱两可?

Dav*_*d W 6 c++ function-templates name-lookup argument-dependent-lookup

前几天,我偶然发现了这个问题,无法弄清楚哪个答案是正确的,或者都不能接受。

具体来说,我指的是对OtherFunction中的bar(T {})的调用。从我已经能够在编译器资源管理器上进行测试的角度来看,这个决定似乎有些分歧。当gcc和clang编译代码没有问题时,msvc和icc同意它是模棱两可的。

通过与参数相关的查找,隐藏的命名空间中的功能栏变得可见。此外,msvc / icc将全局命名空间中的bar声明视为候选,而gcc / clang则不这样做。似乎不应该考虑全局命名空间中的声明,因为它是在调用bar(T {})之后声明的,但是我不确定我是在正确读取不合格名称查找的规则还是标准是在这方面模棱两可。

https://godbolt.org/z/HAS-Cv

编辑:只要使用/ permissive-选项,看起来msvc已修复此问题(https://devblogs.microsoft.com/cppblog/two-phase-name-lookup-support-comes-to-msvc/

template <typename T>
inline void OtherFunction () {
    bar(T{});
}

namespace hidden {
    struct Foo {};
    inline void bar (Foo foo) {}
}

inline void bar (hidden::Foo foo) {}

void Function () {
    OtherFunction<hidden::Foo>();
}
Run Code Online (Sandbox Code Playgroud)

son*_*yao 3

Gcc 和 Clang 是正确的。bar定义后定义的全局通过名称查找OtherFunction找不到;而可以通过ADL找到。hidden::bar

(强调我的)

对于模板定义中使用的依赖名称,查找将被推迟,直到模板参数已知为止,此时 ADL 检查with external linkage (until C++11)从模板定义上下文以及模板实例化上下文中可见的函数声明,而非 ADL 查找仅检查with external linkage (until C++11)从模板定义上下文中可见的函数声明(换句话说,在模板定义之后添加新函数声明不会使其可见,除非通过 ADL)。