首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11中操作符的查找规则

C++11中操作符的查找规则
EN

Stack Overflow用户
提问于 2012-12-13 21:54:47
回答 3查看 607关注 0票数 15

N3337的“工作草案,编程语言标准C++”在第13.3.1.2条第10页给出了以下示例:

代码语言:javascript
复制
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的同样方式编写的。

代码语言:javascript
复制
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的错误:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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);
                     ^

编译器是否正确地让块声明在一种情况下隐藏全局名称,而不是在另一种情况下?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-14 03:01:20

编译器是否正确地让块声明在一种情况下隐藏全局名称,而不是在另一种情况下?

我得出的结论是,这两个编译器都是错误的。我认为x + y;也应该失败。13.3.1.2p3明确规定:

非成员候选集合是根据不限定函数调用(3.4.2)中通常的名称查找规则在表达式上下文中对运算符@进行不限定查找的结果,但所有成员函数都被忽略。

因此,在您的示例中,x + y;operator+(x, y);之间应该没有区别。Commeau在线在代码中产生以下错误:

代码语言:javascript
复制
"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
票数 1
EN

Stack Overflow用户

发布于 2012-12-14 01:53:31

你最初的问题是:

你的结论是正确的。

operator+(a, a);是一个简单的函数调用,因此编译器按照标准顺序搜索潜在的匹配项,查找成员函数,并且不再进一步查找。成员函数不匹配,表达式不正确。

a + a;使用了13.3.1.2 p3中定义的一组稍微不同的规则。首先,一组可能的重载是从A::operator+(a)产生的。然后,从标准的不合格查找中生成可能的重载列表,但忽略成员函数。然后创建一个内置操作符列表。然后使用这三个列表来决定最佳匹配。通常,不合格的查找会在第一步之后停止,如果它发现了什么,这就是为什么它通常会失败的地方工作。

问题2:

从理论上讲,这应该是一样的。不涉及任何成员函数和内置操作符都是无关的,因此它们都应该导致标准的不合格查找。我在标准中找不到任何东西来暗示他们应该有任何不同的地方。除了“它们存在”之外,我在标准中没有看到多少提到块作用域函数声明。毕竟,它们大多只是C的遗物。在标准中,我也没有看到任何具体的规则,以这样或那样的方式说明这是否应该起作用。该标准确实非常强烈地表明,x + yoperator+(x, y)要么都能工作,要么都失败,因为它们都使用相同的方法进行名称查找。

我还没有找到嵌套函数声明的有效用例。

票数 4
EN

Stack Overflow用户

发布于 2013-10-05 14:13:32

关于你的问题第二部分

以下是标准c++11中关于ADL $3.4.2的引用:

设X是非限定查找产生的查找集(3.4.1),Y是由参数相关查找产生的查找集(定义如下)。如果X包含

  • 类成员的声明,或
  • 非使用范围声明的块范围函数声明,或
  • 既不是函数也不是函数模板的声明。

那Y是空的。

..。

似乎,这回答了你的问题

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13869150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档