【问题标题】:Are there different rules regarding ADL or naming clashes with regard to overloaded operators?关于重载运算符的 ADL 或命名冲突是否有不同的规则?
【发布时间】:2014-08-01 19:38:27
【问题描述】:

我认为这个例子最能说明我的问题:

namespace N {

    class C {
    public:
        friend bool operator==(const C& c, const C& x) {
            return true;
        }
        friend bool f(const C& c, const C& x) {
            return true;
        }
    };

    class D {
    public:
        bool operator==(const D& x) {
            bool a = C{} == C{};      // this works
            return true;
        }
        bool f(const D& x) {
            bool a = f(C{}, C{});     // this does not work
            return true;
        }
    };
}

我一直认为重载运算符就像函数一样,除了“调用语法”,如果你愿意的话。我只是在 ADL 或名称查找规则中注意到了上述差异(我不知道是哪一个)。

有人可以解释为什么找到了bool operator==(const C& c, const C& x),但没有找到bool f(const C& c, const C& x)?

【问题讨论】:

  • 请注意,这是隐藏的,而不是 ADL,因为所有内容都在同一个命名空间中。 ADL 是关于在额外的命名空间(特别是定义参数类型的命名空间)中查找函数。

标签: c++ argument-dependent-lookup token-name-resolution


【解决方案1】:

您的D::f 正在隐藏 C::f;如果您将后者重命名为C::g 并调整调用,那么它工作正常(表明该函数可以找到和访问就好了)。

您的代码实际上并没有直接调用运算符函数,但这是由语言为您完成的。因此,您没有使用运算符函数的 name,因此不应用名称隐藏。

如果您写operator==(C{}, C{})(而不是C{} == C{}),那么您将看到与f(C{}, C{})(demo)相同的行为。

所以,当你说“我一直认为重载运算符就像函数一样,除了'调用语法',如果你愿意的话”,你已经一针见血了。


这里有一些标准的给你:

[C++11: 13.5/4]: 运算符函数通常不直接调用;相反,它们被调用来评估它们实现的运算符(13.5.1 - 13.5.7)。但是,可以使用 operator-function-id 作为函数调用语法 (5.2.2) 中的函数名称来显式调用它们。 [示例:

complex z = a.operator+(b); // complex z = a+b;
void* p = operator new(sizeof(int)*n);

——结束示例]

[C++11: 3.3.7/4]: [..] 4) 在成员函数中声明的名称隐藏了同名的声明,其范围扩展到或超过成员函数类的末尾。 [..]

[C++11: 3/4]: 名称是标识符 (2.11)、operator-function-id (13.5)、literal-operator-id (13.5.8)、conversion-function-id (12.3.2) 或 template-id (14.2),表示实体或 标签 (6.6.4, 6.1)。

(这里的 [qualified] operator-function-id 是::N::C::operator==。)

【讨论】:

    猜你喜欢
    • 2014-04-30
    • 2013-06-18
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多