【问题标题】:Deleted implicitly-declared copy assignment operator删除了隐式声明的复制赋值运算符
【发布时间】:2019-04-12 07:29:41
【问题描述】:

根据Copy assignment operator上的C++参考:

如果以下任何一项为真,则将类 T 的默认复制赋值运算符定义为删除

T 有一个非类类型(或其数组)的非静态数据成员,即 const ...

我希望创建一个案例,其中我有一个 const 类类型数据成员和一个未定义为已删除的默认复制赋值运算符。在这样做的过程中,我发现了 clang 和 gcc 之间的差异。考虑以下代码:

struct B {
  void operator=(const B&) const {}
};

struct A {
  const B b{};
  A& operator=(const A&) = default;
};

int main() {
  A a1{}, a2{};
  a1 = a2;       //only works with clang
  B b1{}, b2{};
  b1 = b2;       //works in both
}

当我使用 g++ -std=c++14 编译它时,我收到以下错误:

In member function ‘A& A::operator=(const A&)’:
error: non-static const member ‘const B A::b’, can’t use default assignment operator
note: synthesized method ‘A& A::operator=(const A&)’ first required here

但是,逗号确实可以使用clang 进行编译,因为参考似乎表明它应该这样做。我错了吗?哪个编译器是正确的?

我正在使用gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)clang version 6.0.0-1ubuntu2

【问题讨论】:

  • 一般而言,您希望使用C++,因为与 C++ 版本特定标签相比,这为问题提供了更广泛的受众。

标签: c++ g++ c++14 clang++ assignment-operator


【解决方案1】:

看来clang是对的,

虽然还没有得到确认,但是有一个report关于gcc的主题 正如有人指出的那样,与本案相关的两条规则不适用

[class.copy.assign]/7

(7.2) const 非类类型(或其数组)的非静态数据成员,或

[...]

(7.4) 类类型 M(或其数组)的直接非静态数据成员或由于重载决议([over.match])而无法复制/移动的直接基类 M,应用于查找 M相应的赋值运算符,会导致歧义或函数从默认赋值运算符中删除或无法访问。

【讨论】:

    【解决方案2】:

    看起来clang是正确的,[class.copy.assign]p7部分说:

    类 X 的默认复制/移动赋值运算符定义为 如果 X 有,则删除:

    • (7.1) 具有非平凡对应赋值运算符且 X 是类联合类的变体成员,或
    • (7.2) const 非类类型(或其数组)的非静态数据成员,或
    • (7.3) 引用类型的非静态数据成员,或
    • (7.4) 类类型 M(或其数组)的直接非静态数据成员或无法复制/移动的直接基类 M,因为 重载决议([over.match]),用于查找 M 相应的赋值运算符,导致歧义或 从默认分配中删除或无法访问的功能 运算符。

    定义为已删除的默认移动赋值运算符是 被重载决议忽略([over.match],[over.over])。

    这些情况都不成立。

    虽然我不得不说一个返回 void 的 const 复制赋值运算符感觉很新颖,但[class.copy.assign]p1 中的措辞似乎确实允许。

    有一个类似案例Const subobject with const assignment operator, but operator anyway deleted的开放gcc错误报告,代码如下:

    class bar
    {
    public:
        bar() {}
    
        bar const & operator=(bar const &) const
        {
            return *this;
        }
    };
    
    class foo
    {
        bar const v;
    };
    
    int main()
    {
        foo a;
    
        a = foo();
    }
    

    记者指出与我相同的部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 2015-01-12
      • 2012-07-20
      • 2020-04-09
      • 1970-01-01
      • 1970-01-01
      • 2013-03-23
      相关资源
      最近更新 更多