命名空间作用域中的运算符在全局范围中隐藏

Tom*_*miT 13 c++ namespaces name-lookup

这是编译器错误吗?

template <typename T>
T& operator++(T& t)
{
    return t;
}

namespace asdf {

enum Foo { };
enum Bar { };

Foo& operator++(Foo& foo);

void fun()
{
    Bar bar;
    ++bar;
}

} // end namespace asdf

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC 4.7错误消息是:

error: no match for 'operator++' in '++bar'
note: candidate is:
note: asdf::Foo& asdf::operator++(asdf::Foo&)
note: no known conversion for argument 1 from 'asdf::Bar' to 'asdf::Foo&'
Run Code Online (Sandbox Code Playgroud)

如果您注释掉该行,它会编译:

Foo& operator++(Foo& foo);
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 14

不,这不是一个错误.考虑了三组并行的运算符.成员,非成员运营商和内置运营商.

通过正常的非限定+ ADL查找查找非成员查找,忽略所有类成员函数.因此,全局运算符被词汇更接近的一个隐藏(并且干预成员函数不会隐藏其他非成员).

请注意,重载解析发生名称查找1之后 ; 在你的情况下,operator++找到了名称,但没有适当的超载.

如果Bar已被全局声明,和/或名称空间asdf中的其他运算符,则ADL(在前一种情况下)或普通的非限定查找(在后一种情况下)将拖动运算符.


1:Overload resolution (...) takes place after name lookup has succeeded.(C++标准)


Bar*_*nau 8

不,这不是编译器错误.

为表达式执行了两个名称查找++bar.

  • 常规名称查找搜索封闭范围和命名空间,直到找到第一的occurence operator++.此搜索内部工作,因此最后搜索全局命名空间.查找运算符函数时,会单独处理成员函数(并且不会停止此搜索).
  • 依赖于参数的查找将接下来并搜索其他类和名称空间,但仅搜索与函数的参数相关的那些(operator++在本例中).

在问题的示例中,正常查找查找asdf::operator++并停止查找.
依赖于参数的查找仅将asdf命名空间添加到要搜索的位置,因为这是相关的命名空间enum Bar.因此,operator++无法找到全局.

您可以operator++使用命名空间中的using声明来查找全局asdf.