这是编译器错误吗?
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;
}
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&'
如果您注释掉该行,则会编译:
Foo& operator++(Foo& foo);
答案 0 :(得分:14)
不,这不是一个错误。考虑了三组并行的运算符。成员,非成员运营商和内置。
通过正常的非限定+ ADL查找查找非成员查找,忽略所有类成员函数。因此,全局运算符被词汇更接近的隐藏(并且介入成员函数不会隐藏其他非成员)。
请注意,在名称查找 1 之后,会发生重载解析;在您的情况下,找到了名称operator++
,但没有适当的超载。
如果Bar已被全局声明,和/或名称空间asdf中的其他运算符,ADL(在前一种情况下)或普通的非限定查找(在后一种情况下)将拖动运算符。
1 :Overload resolution (...) takes place after name lookup has succeeded.
(C ++标准版)
答案 1 :(得分:8)
不,这不是编译器错误。
对表达式++bar
执行了两次名称查找。
operator++
的第一个出现。此搜索内部工作,因此最后搜索全局命名空间。在查找运算符函数时,会单独处理成员函数(并且不会停止此搜索)。operator++
)。在问题的示例中,正常查找找到asdf::operator++
并停止查看
依赖于参数的查找仅将asdf
命名空间添加到要搜索的位置,因为这是enum Bar
的关联命名空间。因此,无法找到全局operator++
。
您可以使用名称空间operator++
中的使用声明来查找全局asdf
。
答案 2 :(得分:1)
重载仅适用于在同一范围内定义的名称。一旦编译器找到匹配的名称,它就不会在外部作用域中查找,即使它找到的名称适用于无法使用的名称。这与运营商无关;如果代码使用函数名称的方式与使用operator ++相同,则会得到相同的错误。例如:
void f(int);
struct C {
void f(const C&);
void g() {
f(3); // error: f(const C&) can't be called with argument 3
};