删除了隐式声明的复制赋值运算符

Deleted implicitly-declared copy assignment operator

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

A defaulted copy assignment operator for class T is defined as deleted if any of the following is true

T has a non-static data member of non-class type (or array thereof) that is const ...

我希望创建一个案例,其中我有一个 const class 类型的数据成员和一个未定义为已删除的默认复制赋值运算符。在这样做的过程中,我发现了 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

看起来 clang 确实是正确的,第 [class.copy.assign]p7 节说:

A defaulted copy/move assignment operator for class X is defined as deleted if X has:

  • (7.1) a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or
  • (7.2) a non-static data member of const non-class type (or array thereof), or
  • (7.3) a non-static data member of reference type, or
  • (7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.

A defaulted move assignment operator that is defined as deleted is ignored by overload resolution ([over.match], [over.over]).

和 none 这些情况成立。

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

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

class bar
{
public:
    bar() {}

    bar const & operator=(bar const &) const
    {
        return *this;
    }
};

class foo
{
    bar const v;
};

int main()
{
    foo a;

    a = foo();
}

记者指的是和我一样的版块

看来clang说的对,

虽然尚未确认,但关于 gcc 的主题有 report 正如所指出的那样,与本案相关的两条规则不适用

[class.copy.assign]/7

(7.2) a non-static data member of const non-class type (or array thereof), or

[...]

(7.4) a direct non-static data member of class type M (or array thereof) or a direct base class M that cannot be copied/moved because overload resolution ([over.match]), as applied to find M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.