什么是C++名称查找在这里做什么?(&GCC对吧?)

Eva*_*nED 10 c++ argument-dependent-lookup

我在一些生产代码中遇到问题,我将其最小化到以下测试用例:

template<typename T>
void intermediate(T t)
{
    func(t); // line 4 ("func not declared in this scope")
}

namespace ns {
    struct type {};
}

void func(ns::type const & p); // line 11 ("declared here, later")

void foo(ns::type exit_node)
{
    intermediate(exit_node);  // line 15 ("required from here")
}
Run Code Online (Sandbox Code Playgroud)

GCC 4.5汇编了这个罚款.有和没有-std=c++11,4.7和4.9产生如下消息:

test.cpp: In instantiation of ‘void intermediate(T) [with T = ns::type]’:
test.cpp:15:27:   required from here
test.cpp:4:5: error: ‘func’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
test.cpp:11:6: note: ‘void func(const ns::type&)’ declared here, later in the translation unit
Run Code Online (Sandbox Code Playgroud)

以下所有三件事都会导致文件成功编译:

  1. 移动func(ns::type)ns命名空间(允许ADL找到它ns)
  2. 移动type到全局命名空间(允许ADL找到它::)
  3. 摆脱intermediatefunc直接打电话foo

那么......这里发生了什么?海湾合作委员会拒绝该计划是否合法?为什么func在第三个变量中找到非限定查找(func直接调用foo),但在实例化时原始变量中的非限定查找找不到?

T.C*_*.C. 7

一般规则是,模板定义上下文中的任何内容都只能通过ADL获取.换句话说,仅在模板定义上下文中执行正常的非限定查找.

由于funcintermediate定义时没有声明是可见的,并且func不在与之关联的命名空间中ns::type,因此代码是不正确的.