Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 297
Nathan Chappell Avatar asked Nov 08 '18 18:11

Nathan Chappell


People also ask

What is a copy assignment operator?

A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter of type T, T&, const T&, volatile T&, or const volatile T&. For a type to be CopyAssignable, it must have a public copy assignment operator.

What is the default assignment operator?

If a class definition does not declare a parameterless constructor, a copy constructor, a copy assignment operator, or a destructor, the compiler will implicitly declare them. These are called default operators.

What is difference between copy constructor and assignment operator?

The difference between a copy constructor and an assignment operator is that a copy constructor helps to create a copy of an already existing object without altering the original value of the created object, whereas an assignment operator helps to assign a new value to a data member or an object in the program.

Why is copy assignment operator needed?

Both the copy constructors and assignment operators copies from one object to another then why do we need both? Copyconstructor means it creates a new object and copies the contents from another exist object and assignment operator copies the contents from one existing object to the already existing object.


2 Answers

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.

like image 175
Jans Avatar answered Sep 30 '22 16:09

Jans


It sure looks like clang is correct, section [class.copy.assign]p7 says:

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

and none of those cases hold.

Although I have to say a const copy assignment operator that returns void feels novel, the wording in [class.copy.assign]p1 sure seems to allow.

There is an open gcc bug report for a similar case Const subobject with const assignment operator, but operator anyway deleted with code as follows:

class bar
{
public:
    bar() {}

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

class foo
{
    bar const v;
};

int main()
{
    foo a;

    a = foo();
}

The reporter points out the same section as I do.

like image 36
Shafik Yaghmour Avatar answered Sep 30 '22 16:09

Shafik Yaghmour