2

In Stroustrup's Tour of C++ he mentions:

If you are explicit about some defaults, other default definitions will not be generated.

However, this doesn't seem to be the case with gcc 4.9.1. Take for example:

#include <iostream>
using namespace std;

struct A 
{
    int data;
    A() = default;
    A(const A&) = default;
};

int main() 
{

  A a;
  a.data = 10;
  A b(a);
  A c;
  c = a;

  cout<<b.data<<endl;
  cout<<c.data<<endl;
  return 0;
}

It compiles and gives the expected output. i.e. the default assignment operator has been generated.

Did I misunderstand Stroustrup's comment?

Mustafa
  • 1,814
  • 3
  • 17
  • 25

2 Answers2

5

Firstly, your code doesn't use the class's assignment operator, so it doesn't demonstrate that it exists. However, adding a use of it

c = a;

will work, so the question still stands.

It's not the case that declaring any special function prevents all other special functions from being generated, which seems to be how you're interpreting the quote. Declaring some will inhibit some others. Not having read the book to put the quote in context, I can't say whether or not it's misleading.

The rules are, roughly:

  • declaring any constructor will prevent an implicit default constructor;
  • declaring a move constructor or move-assignment operator will prevent an implicit copy constructor and copy-assignment operator;
  • declaring a destructor, copy constructor or copy-assignment operator will prevent an implicit move constructor and move-assignment operator;

That's a simplification; there are more nuances and exceptions. Read the language specification if you want the gory details.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Okay, I quoted him literally. I think he should have said "If you are explicit about some defaults, **some** other default definitions will not be generated." – Mustafa Dec 12 '14 at 17:13
  • Getting a defaulted copy constructor in the presence of an *user-declared copy constructor* is said to be deprecated in C++11. – Pixelchemist Dec 12 '14 at 17:24
  • @Pixelchemist: Indeed, there are nuances to the rules that I didn't mention. For the gory details, read the standard. – Mike Seymour Dec 12 '14 at 17:26
  • While his wording certainly causes some ambiguity, I think you've missed something here. Stroustrup states that `If any move, copy, or destructor is explicitly specified ... any undeclared copy operations are generated by default, but this is deprecated`. This implies that they are currently generated by default, but this behavior is subject to be removed at any time. – Julian Dec 12 '14 at 17:28
  • 1
    @AtlasC1: Indeed, there are circumstances where the implicit generation is deprecated. This is a rough simplification of the rules as they are now, not an attempt to cover every detail of the 20+ pages of the standard describing special member functions. – Mike Seymour Dec 12 '14 at 17:33
0

Those declarations are currently generated by default (which is why the code you provided works), but this behavior is subject to be removed at any time in further revisions to the C++ standard (deprecated).

In Stroustrup's C++11 FAQ, he states

If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, no move is generated by default.

That is pretty self explanatory. However, he goes on to say that...

If any move, copy, or destructor is explicitly specified (declared, defined, =default, or =delete) by the user, any undeclared copy operations are generated by default, but this is deprecated, so don't rely on that.

He then lists a few examples:

class X1 {
    X1& operator=(const X1&) = delete;  // Disallow copying
};

This implicitly also disallows moving of X1s. Copy initialization is allowed, but deprecated.

class X2 {
    X2& operator=(const X2&) = delete;
};

This implicitly also disallows moving of X2s. Copy initialization is allowed, but deprecated.

class X3 {
    X3& operator=(X3&&) = delete;   // Disallow moving
};

This implicitly also disallows copying of X3s.

class X4 {
    ~X4() = delete; // Disallow destruction
};

This implicitly also disallows moving of X4s. Copying is allowed, but deprecated.

Julian
  • 1,688
  • 1
  • 12
  • 19
  • Okay, I think it is a language issue. See my comment to Seymour's [answer](http://stackoverflow.com/questions/27448251/incomplete-verbosity-of-default-definitions-declarations/27448442#27448442) below. – Mustafa Dec 12 '14 at 17:16
  • 1
    @mustafa While his wording certainly causes some ambiguity, I think you've missed something here. Stroustrup states that If any move, copy, or destructor is explicitly specified ... any undeclared copy operations are generated by default, but this is deprecated. This implies that they are currently generated by default, but this behavior is subject to be removed at any time. – Julian Dec 12 '14 at 17:29