Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does [C++11: 12.8/7] make sense?

Tags:

c++

c++11

[C++11: 12.8/7]: If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. Thus, for the class definition

struct X {
   X(const X&, int);
};

a copy constructor is implicitly-declared. If the user-declared constructor is later defined as

X::X(const X& x, int i =0) { /* ... */ }

then any use of X’s copy constructor is ill-formed because of the ambiguity; no diagnostic is required.

This doesn't make a lot of sense to me.

How does the code sample introduced by "thus" have anything to do with the "latter" case that I highlighted in italics?

My understanding so far is that:

  • If the class definition does not explicitly declare a copy constructor, and
  • the class definition does not declare a move constructor or move assignment operator, and
  • the class has a use-declared copy assignment operator or a user-declared destructor, then
  • the implicitly-defined copy constructor is defined as defaulted, and this is deprecated.

This seems odd in itself, that a standard-mandated behaviour is — in the same breath — deprecated. Does this mean that having a class that satisfies those three conditions is deprecated?

And what does the code sample have to do with it? That constructor is not a copy constructor, move constructor, move assignment operator, copy assignment operator or a user-declared destructor; it's just a user-declared constructor, no? Where's this "ambiguity"?

Could someone decode this passage for me?

like image 375
Lightness Races in Orbit Avatar asked Feb 22 '23 20:02

Lightness Races in Orbit


1 Answers

Does this mean that having a class that satisfies those three conditions is deprecated?

Yes; if you have a use-declared copy-assignment operator or destructor, you should also declare a copy constructor. It's basically just saying that your class should follow the Rule of Three (or Five, or whatever it's called in C++11).

This seems odd in itself, that a standard-mandated behaviour is — in the same breath — deprecated.

The behaviour is mandated by the standard because that was the behaviour in C++03 - changing it would break legacy code. Just as the standard defines the behaviour of (for example) dynamic exception specifications, and also deprecates them.

How does the code sample introduced by "thus" have anything to do with the "latter" case that I highlighted in italics?

It doesn't have anything to do with the "latter" case.

It is an illustration of a potential problem caused by the normal behaviour defined by the clause: there will be a conflict between an implicitly-declared copy constructor, and a user-declared constructor with default arguments such that it can be called like a copy constructor.

Where's this "ambiguity"?

Consider the code:

X x1;  // assume there's also a default constructor
X x2(x);

Should x2 be initialised with the user-declared constructor (with the second argument taking its default value), or the implicitly-declared copy constructor? Both are an equally good match for the usage. That is the ambiguity.

like image 80
Mike Seymour Avatar answered Feb 27 '23 12:02

Mike Seymour