【问题标题】:Can't delete only const overload of method?不能只删除方法的 const 重载吗?
【发布时间】:2017-05-02 19:47:15
【问题描述】:

至少对于一元 & 和一元 - 来说,GCC 似乎只会让您删除运算符的非常量和常量版本,或者不删除(它可能会影响二元运算符,但我没有检查过)。如下面的 cmets 所述,虽然我可以基于 const 成功重载,但我无法单独删除 const 或非 const 重载而不会遇到编译错误。此行为标准是否符合?这似乎违反直觉。

使用 GCC 5.4.0 测试。

#include <iostream>

struct A {
    // These both being defined at the same time is fine,
    // and whether or not x is const as expected will change
    // which overload you get.

    A* operator&() {
        std::cout << "hello" << std::endl;
        return this;
    }

    const A* operator&() const {
        std::cout << "world" << std::endl;
        return this;
    }



    // assuming both definitions above are commented out,
    // regardless of whether or not x is const
    // either one of these lines being present
    // will make the example not compile!

    // A* operator&() = delete;
    // const A* operator&() const = delete;



    // Finally if you have the const version defined and the non-const version deleted
    // or vice versa, it will compile as long as the one that you have defined
    // matches the constness of x.
};

int main(int argc, char** argv)
{
    A x;
    std::cout << &x << std::endl;
    return 0;
}

【问题讨论】:

  • 可以在非const 对象上调用const 成员函数。我不确定你在期待什么。
  • @T.C.可以,但是即使不调用它也会发生错误(当 x 是非常量并且仅删除 const 版本时)。它也发生在相反的情况下(const x 仅删除了非常量版本)。我试图说明这一点,但这确实很棘手。
  • 在上面的代码中,如果您注释 const A* operator&amp;() const { ... } 并取消注释 const A* operator&amp;() const = delete;,它将编译为非 const A 对象。同样,您可以通过注释/取消注释其他组合来编译const A,那么您的问题是什么?而不是代码中的所有这些 cmets,也许尝试发布所有不会编译的版本。
  • @Praetorian 我试图解释这将在第三个评论块中起作用。尝试按照第二个评论块中的说明进行操作:coliru.stacked-crooked.com/a/8ebec6956aae7ace
  • 正如 TC 已经说过的,const 成员函数可以在非const 对象上调用,并且删除的函数是您示例中唯一可用的候选函数,因此它当然不会编译。您可以创建对象const,但由于同样的原因它仍然无法编译。

标签: c++ c++11 operator-overloading overloading


【解决方案1】:

内置的operator&amp; 不参与重载解析([over.match.oper]/3.3)。

对于operator ,unary operator &amp;operator -&gt;,内置候选集为空。

假设你声明删除了下面的重载

const A* operator&() const = delete;

无论您是尝试获取const 还是非const A 的地址,上面的声明都是唯一可行的候选者,这会导致编译错误。

如果将其注释掉,则根据[over.match.oper]/9 找到内置的operator&amp;

如果运算符是operator ,unary operator &amp;,或operator -&gt;并且没有可行的函数,则假定运算符是内置的in 运算符 并根据子句 [expr] 进行解释。

现在,如果您将非const 重载声明为已删除

A* operator&() = delete;

这不能在 const A 对象上调用,因此它不是一个可行的候选对象,并且会找到内置的 operator&amp;

Live demo


在处理重载operator&amp;的类时,可以使用std::addressof获取实例的地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-21
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多