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
以下所有三件事都会导致文件成功编译:
- 将
func(ns::type)
移动到 ns
命名空间(允许 ADL 在 ns
中找到它)
- 将
type
移动到全局命名空间中(允许 ADL 在 ::
中找到它)
- 摆脱
intermediate
并直接从foo
调用func
所以...这是怎么回事? GCC 拒绝该程序是否合法?为什么在第三个变体(直接从foo
调用func
)中通过非限定查找找到func
,但在实例化时在原始变体中通过非限定查找找不到?
GCC 是对的。 func
只能通过 ADL 找到,因为它是一个不合格的依赖函数调用。 func
是在全局命名空间中声明的,但是 不是 ns::type
的关联命名空间,只有 ns
是(这就是您当前代码失败的原因).当你把intermediate(exit_node)
替换成直接调用foo
里面的func(exit_node)
,那么就是通过正常的不合格查找找到的。
一般规则是,任何不在模板定义上下文中的内容都只能通过 ADL 获取。换句话说,正常的非限定查找仅在模板定义上下文中执行。
由于在定义 intermediate
时 func
的声明不可见,并且 func
不在与 ns::type
关联的命名空间中,因此代码格式错误.
我在一些生产代码中遇到问题,我将其最小化为以下测试用例:
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
并直接从foo
调用func
所以...这是怎么回事? GCC 拒绝该程序是否合法?为什么在第三个变体(直接从foo
调用func
)中通过非限定查找找到func
,但在实例化时在原始变体中通过非限定查找找不到?
GCC 是对的。 func
只能通过 ADL 找到,因为它是一个不合格的依赖函数调用。 func
是在全局命名空间中声明的,但是 不是 ns::type
的关联命名空间,只有 ns
是(这就是您当前代码失败的原因).当你把intermediate(exit_node)
替换成直接调用foo
里面的func(exit_node)
,那么就是通过正常的不合格查找找到的。
一般规则是,任何不在模板定义上下文中的内容都只能通过 ADL 获取。换句话说,正常的非限定查找仅在模板定义上下文中执行。
由于在定义 intermediate
时 func
的声明不可见,并且 func
不在与 ns::type
关联的命名空间中,因此代码格式错误.