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

What is C++ name lookup doing here? (& is GCC right?)

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

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")
}

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

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

  1. func(ns::type) 移动到 ns 命名空间(允许 ADL 在 ns 中找到它)
  2. type 移动到全局命名空间中(允许 ADL 在 :: 中找到它)
  3. 摆脱intermediate并直接从foo调用func

所以...这是怎么回事? GCC 拒绝该程序是否合法?为什么在第三个变体(直接从foo调用func)中通过非限定查找找到func,但在实例化时在原始变体中通过非限定查找找不到?

GCC 是对的。 func 只能通过 ADL 找到,因为它是一个不合格的依赖函数调用。 func 是在全局命名空间中声明的,但是 不是 ns::type 的关联命名空间,只有 ns 是(这就是您当前代码失败的原因).当你把intermediate(exit_node)替换成直接调用foo里面的func(exit_node),那么就是通过正常的不合格查找找到的。

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

由于在定义 intermediatefunc 的声明不可见,并且 func 不在与 ns::type 关联的命名空间中,因此代码格式错误.