8

Say a class

class Piece {} ;

If I'm correct that should be equivalent to :

class Piece {
   //C++ 03
    Piece ();                          //default constructor
    Piece( const Piece&);              //copy constructor
    Piece& operator=(const Piece&);    //copy assignment operator
    ~Piece();                          //destructor

    //Since C++ 11
    Piece(Piece&&);                   //move constructor
    Piece& operator=(Piece&&);        //move assignment operator
};

So what can I say about these ?

a)

class Pawn{
    ~Pawn() {}// Only destructor
};

b)

class Bishop{
    Bishop(Bishop&& ) {}// Only move constructor
};

c)

class Knight{
    Knight(Knight&&, int =0) {} // move constructor, when no second arg present
};

d)

class Rook {
    Rook(const Rook& ) {}// Only copy constructor
};

e)

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

My per my understanding compiler will generate for :

  • a) Default Constructor, Copy Constructor, Copy Assignment operator , ( move constructor/assignment operator ? )
  • b) Destructor
  • c) Destructor
  • d) Copy Assignment operator and Destructor ( move constructor/assignment operator ? )
  • e) Default Constructor, Copy Constructor, Destructor, ( move constructor/assignment operator ? )

Am I correct or missing something here ?

Basically is C++11 has any new rules for generating functions, when not provided by user ?

P0W
  • 42,046
  • 8
  • 62
  • 107
  • 1
    Your first piece of code is only correct if you put `= default` behind the prototypes. If you implement them yourself they’re no longer trivial and make the class non-POD etc. – Konrad Rudolph Oct 26 '13 at 12:11
  • @KonradRudolph: *"If I'm correct that should be equivalent to"* probably translates to "this generates the following default constructors/assignment operators for me", as it should reflect the operators/constructors available in `class Piece{};` – Zeta Oct 26 '13 at 12:19
  • "Equivalent" is a poor choice of words. There's still a difference, which is about *triviality*, and which is detectable by means of `std::is_trivially_copyable` traits etc. And "the compiler" has nothing to do with this question. The language rules determine what is implicitly declared and implicitly defined. – Kerrek SB Oct 26 '13 at 12:32
  • @KerrekSB sorry, please feel free to re-word/phrase/edit it – P0W Oct 26 '13 at 12:34
  • 1
    It's too painful to spell out all the different cases. I'm pretty sure we have useful posts about this here on SO already, and otherwise get a copy of the standard and just read secion 12.8 yourself. It's very clear and readable. – Kerrek SB Oct 26 '13 at 12:39
  • @KerrekSB yeah, trying to search same on SO too. – P0W Oct 26 '13 at 12:44
  • Search for "rule of five".maybe this answer : http://stackoverflow.com/a/4782927/476681 – BЈовић Oct 26 '13 at 12:53
  • [C++ implicit copy constructor for a class that contains other objects](http://stackoverflow.com/a/1810320/14065) – Martin York Oct 26 '13 at 14:59

2 Answers2

7

I'll leave out some irrelevant points here, e.g. about unions, base classes, brace-or-equal-initializers etc. If your classes have any members, base classes, ... then the answer will differ. For example, if you have a const member, an implicitly declared assignment operator would be defined as deleted.

default constructor

[class.ctor]/5

A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted. An implicitly-declared default constructor is an inline public member of its class. A defaulted default constructor for class X is defined as deleted if [... lots of points irrelevant here].

So in cases a) and e) [without any user-declared ctor], a default ctor is declared as defaulted.

default destructor

[class.dtor]

4 If a class has no user-declared destructor, a destructor is implicitly declared as defaulted. An implicitly-declared destructor is an inline public member of its class.

5 A defaulted destructor for a class X is defined as deleted if [... lots of points irrelevant here]

So in all cases but a) [with a user-declared dtor], a default dtor is implicitly declared and implicitly defined if odr-used.


As per [class.copy]/2+3, a copy-ctor and move-ctor may have additional parameters, if those have default arguments.

copy-constructor

A copy-ctor is declared implicitly if there's no user-defined copy-ctor (a ctor template is never a copy-ctor). [class.copy]/7

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. The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

That is, in all cases but d) [with a user-declared copy-ctor], a copy-ctor is declared implicitly. In cases b) and c) [with a user-provided move ctor], the copy-ctor is defined as deleted. For a) [user-declared dtor] and e) [user-declared copy-assignment op], it may be defined as defaulted, but that's deprecated.

move-constructor

The move-ctor won't even be declared in these cases [class.copy]/9

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

There are again quite some cases where it would be defined as deleted, but they don't apply here.

Therefore, the move-ctor is not declared in any of the cases.


copy-assignment operator

In [class.copy]/18:

If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted. The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor.

It is defined as deleted in some cases, see [class.copy]/23, but they don't apply here.

The copy-assignment op is declared in all cases but e) [user-declared copy-assignment op]. It is defined as deleted in b) and c) [both: user-declared move ctor]; and it may be defined as defaulted in a) [user-declared dtor] and d) [user-declared copy-ctor]. Note the parallel to the copy-ctor.

move-assignment operator

Similar to the move-ctor, the move-assignment op is not even declared if either [class.copy]/20:

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared move constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared destructor, and
  • the move assignment operator would not be implicitly defined as deleted.

It is defined as deleted in some cases, see [class.copy]/23 (same paragraph as for the copy-ctor), but they don't apply here.

A move-assignment-op is declared implicitly and defined as defaulted in none of the cases.

dyp
  • 35,820
  • 10
  • 96
  • 156
  • I thought one (for example copy constructor) is deleted, if one of the others is even declared (for example destructor) – BЈовић Oct 26 '13 at 13:31
  • @BЈовић Well that's true for the move-ctor and move-assignment op, but not for their copy counterparts. Maybe because of compatibility? Declared but deleted functions participate in overload resolution. – dyp Oct 26 '13 at 13:34
  • Thanks, for the references – P0W Oct 26 '13 at 13:50
3

So looking at some post and online tutorials, I concluded this :

Generated functions :-

  • C++ 03:

    1) Default Constructor (generated only if no constructor is declared by user)

    2) Copy Constructor (generated only if No. 5,6 declared by user)

    3) Copy Assignment operator (generated only if 5,6 not declared by user)

    4) Destructor

  • Since C++ 11:

    5) Move Constructor (generated only if 2,3,4,6 not declared by user)

    6) Move Assignment Operator (generated only if 2,3,4,5 not declared by user)


So, for

a)

class Pawn{ //1, 2, 3
    ~Pawn() {}// Only destructor
};

b)

class Bishop{ //4
    Bishop(Bishop&& ) {}
};

c)

class Knight{ //4
    Knight(Knight&&, int =0) {} 
};

d)

class Rook { //3, 4
    Rook(const Rook& ) {}
};

e)

class King{ //1, 2, 4
        King& operator=(const King&) = delete;
    };

Edit : As per DyP comment :-

In C++11,

For case a), 2 and 3 are deprecated.

For case d), 3 is deprecated.

For case e), 2 is deprecated.

P0W
  • 42,046
  • 8
  • 62
  • 107