Search code examples
c++g++c++14clang++assignment-operator

Deleted implicitly-declared copy assignment operator


According to the C++ reference on Copy assignment operator:

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 ...

I was hoping to create a case where I had a const class-type data member and a defaulted copy assignment operator not defined as deleted. In doing so, I found a discrepancy between clang and gcc. Consider the following code:

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
}

When I compile this with g++ -std=c++14 I get the following errors:

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

This does, comma, however, compile with clang, as the reference seems to indicate that it should. Am I in error? Which compiler is correct?

I'm using gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) and clang version 6.0.0-1ubuntu2.


Solution

  • It seems that clang is right,

    Although not yet confirmed, there is a report on the subject for gcc and as it was pointed out, the two rules relevant to this case don't apply

    [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.