N3337的“工作草案,编程语言标准C++”在第13.3.1.2条第10页给出了以下示例:
struct A { };
void operator + (A, A);
struct B {
void operator + (B);
void f ();
};
A a;
void B::f() {
operator+ (a,a); // error: global operator hidden by member
a + a; // OK: calls global operator+
}不过,这只是一张纸条:
注意:表达式中操作符的查找规则与函数调用中操作符函数名称的查找规则不同,如下面的示例所示:
我的问题是,在标准中,它是否说这是必须发生的事情,而不是仅仅有一个例子的笔记?
据我所知,根据第13.3.1.2条第2页,操作符表达式被转换为操作符函数调用。那么,为什么以及如何在上面的例子中有区别呢?
编辑:
在研究了这个问题后,我想我可能忽略了第3和第6页,在同一条款中,指出全球候选人和成员候选人在查找运算符时是平等的(因此查找规则与注释中说的不同)。然而,我对这一问题的调查是以GCC 4.8和Clang的同样方式编写的。
struct X {}; struct Y {};
void operator+(X, X) { }
void operator+(X, Y) { }
void test() {
void operator+(X, X);
X x; Y y;
x + x; // OK
x + y; // OK
operator+(x, y); // error
operator+(x, x); // OK
}为什么在直接调用运算符函数而不是由运算符表达式调用运算符函数时,会出现块作用域声明的阴影?
以下是GCC的错误:
operators-main-ss.cpp: In function ‘void test()’:
operators-main-ss.cpp:13:17: error: could not convert ‘y’ from ‘Y’ to ‘X’
operator+(x, y); // error
^这里来自Clang:
operators-main-ss.cpp:13:16: error: no viable conversion from 'Y' to 'X'
operator+(x, y); // error
^
operators-main-ss.cpp:1:8: note: candidate constructor (the implicit copy constructor) not viable: no
known conversion from 'Y' to 'const X &' for 1st argument;
struct X {}; struct Y {};
^
operators-main-ss.cpp:7:22: note: passing argument to parameter here
void operator+(X, X);
^编译器是否正确地让块声明在一种情况下隐藏全局名称,而不是在另一种情况下?
发布于 2012-12-14 03:01:20
编译器是否正确地让块声明在一种情况下隐藏全局名称,而不是在另一种情况下?
我得出的结论是,这两个编译器都是错误的。我认为x + y;也应该失败。13.3.1.2p3明确规定:
非成员候选集合是根据不限定函数调用(3.4.2)中通常的名称查找规则在表达式上下文中对运算符@进行不限定查找的结果,但所有成员函数都被忽略。
因此,在您的示例中,x + y;和operator+(x, y);之间应该没有区别。Commeau在线在代码中产生以下错误:
"ComeauTest.c", line 11: error: no operator "+" matches these operands
operand types are: X + Y
x + y; // OK
^
"ComeauTest.c", line 13: error: no suitable user-defined conversion from "Y"
to "X"
exists
operator+(x, y); // error发布于 2012-12-14 01:53:31
你最初的问题是:
你的结论是正确的。
operator+(a, a);是一个简单的函数调用,因此编译器按照标准顺序搜索潜在的匹配项,查找成员函数,并且不再进一步查找。成员函数不匹配,表达式不正确。
a + a;使用了13.3.1.2 p3中定义的一组稍微不同的规则。首先,一组可能的重载是从A::operator+(a)产生的。然后,从标准的不合格查找中生成可能的重载列表,但忽略成员函数。然后创建一个内置操作符列表。然后使用这三个列表来决定最佳匹配。通常,不合格的查找会在第一步之后停止,如果它发现了什么,这就是为什么它通常会失败的地方工作。
问题2:
从理论上讲,这应该是一样的。不涉及任何成员函数和内置操作符都是无关的,因此它们都应该导致标准的不合格查找。我在标准中找不到任何东西来暗示他们应该有任何不同的地方。除了“它们存在”之外,我在标准中没有看到多少提到块作用域函数声明。毕竟,它们大多只是C的遗物。在标准中,我也没有看到任何具体的规则,以这样或那样的方式说明这是否应该起作用。该标准确实非常强烈地表明,x + y和operator+(x, y)要么都能工作,要么都失败,因为它们都使用相同的方法进行名称查找。
我还没有找到嵌套函数声明的有效用例。
发布于 2013-10-05 14:13:32
关于你的问题第二部分
以下是标准c++11中关于ADL $3.4.2的引用:
设X是非限定查找产生的查找集(3.4.1),Y是由参数相关查找产生的查找集(定义如下)。如果X包含
那Y是空的。
..。
似乎,这回答了你的问题
https://stackoverflow.com/questions/13869150
复制相似问题