我在某些生产代码中出现问题,我将其最小化为以下测试用例:
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
以下所有三件事都会导致文件成功编译:
func(ns::type)
移至ns
命名空间(允许ADL在ns
中找到它)type
移至全局命名空间(允许ADL在::
中找到它)intermediate
并直接从func
foo
醇>
那么......这里发生了什么?海湾合作委员会拒绝该计划是否合法?为什么func
在第三个变体中通过非限定查找找到(直接从func
调用foo
),但在实例化时原始变体中的非限定查找找不到?
答案 0 :(得分:7)
一般规则是,模板定义上下文中的任何内容都只能通过ADL获取。换句话说,正常的非限定查找仅在模板定义上下文中执行。
由于在定义func
时未显示intermediate
的声明,并且func
不在与ns::type
关联的命名空间中,因此代码格式不正确。< / p>
答案 1 :(得分:3)
func
只能通过ADL找到,因为它是一个不合格的依赖函数调用。 func
在全局命名空间中声明,但不是ns::type
的关联命名空间,只有ns
(这就是您当前代码失败的原因)。当您通过直接调用intermediate(exit_node)
内的func(exit_node)
替换foo
时,会通过正常的非限定查找找到它。