3

I was reading this: https://en.cppreference.com/w/cpp/language/rule_of_three

And my understanding from this is that, if you want to have a base class with a virtual destructor, the you need to define all 5 special functions (extracted from the rule of 0 section):

class base_of_five_defaults
{
 public:
    base_of_five_defaults(const base_of_five_defaults&) = default;
    base_of_five_defaults(base_of_five_defaults&&) = default;
    base_of_five_defaults& operator=(const base_of_five_defaults&) = default;
    base_of_five_defaults& operator=(base_of_five_defaults&&) = default;
    virtual ~base_of_five_defaults() = default;
};

however when I try to instaiate that class I get the error saying that "default c'tor is not created":

    base_of_five_defaults b; // Error

Then if I generate the default its ok:

base_of_five_defaults() = default;

But I did not understand that this was needed at all... so I am confused why its not there. I thought the only reason the compiler does not generate a default constructor is if you specify a non-default constructor...

If you DO need to specify the default c'tor then the class in the example is un-constructable - which seems odd.

Here is the link to my full live example: https://godbolt.org/z/qPvjd6r51


From https://en.cppreference.com/w/cpp/language/default_constructor:

Implicitly-declared default constructor

If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.

I guess this means if base_of_five_defaults(const base_of_five_defaults&) = default; is declared then it is considered user-declared even though its "default"?

YSC
  • 38,212
  • 9
  • 96
  • 149
code_fodder
  • 15,263
  • 17
  • 90
  • 167
  • 1
    its meant to be used as base class (though that does not change the fact that it is not possible to construct it) – 463035818_is_not_an_ai May 19 '21 at 10:31
  • @largest_prime_is_463035818 but a base class *can* be constructable unless its specifically abstracted... but I see your point - I do find the example a bit odd though :) – code_fodder May 19 '21 at 10:35
  • the example is in contrast to "C.21: If you define or =delete any copy, move, or destructor function, define or =delete them all" Either I am missing something, or they just missed to include it in the example. Actually I am not sure how to take `base_of_five_defaults`, is it meant as a real utlity or merely to demonstrate the point? I am leaning towards the latter – 463035818_is_not_an_ai May 19 '21 at 10:42
  • Because you defined at least one explicit ctor, thus implicit default ctor is removed? – Jean-Baptiste Yunès May 19 '21 at 10:44
  • oh wait a sec. I misread C21. It actually does not mention constructors. There must be something I am missing ;) – 463035818_is_not_an_ai May 19 '21 at 10:44
  • After edit: yes, implicit ctor is not the same as explicitly defined ctor associated to the default implementation. – Jean-Baptiste Yunès May 19 '21 at 10:46
  • related: https://stackoverflow.com/questions/40959659/c-rule-of-zero-what-is-user-declared-constructor – 463035818_is_not_an_ai May 19 '21 at 10:46
  • I updated my question - which I think boils down to is `base_of_five_defaults(const base_of_five_defaults&) = default;` user defined? - I guess that it is – code_fodder May 19 '21 at 10:47
  • @largest_prime_is_463035818 - ah, I think the answer in there says that *any* c'tor written by the user is user-declared (sounds a bit obvious when put that way)... so the example is just a bit of a "mis-lead" from my point of view :) – code_fodder May 19 '21 at 10:49
  • @Jean-BaptisteYunès thanks - I think that was the bit of info I was missing – code_fodder May 19 '21 at 10:49
  • please add as a answers - or perhaps we can close this question ... – code_fodder May 19 '21 at 10:50

1 Answers1

1

I guess this means if base_of_five_defaults(const base_of_five_defaults&) = default; is declared then it is considered user-declared even though its "default"?

Yes. base_of_five_defaults(base_of_five_defaults&&) = default; declares a1 defaulted user-declared constructor.

The = default makes the compiler generate the definition of such a constructor, but it has been declared by the user.

The C++ standard does not provide an explicit definition of user-declared so English kicks in for it to mean, well, "declared by the user".

This is where [class.default.ctor]/1 bites you:

[class.default.ctor]/1

A default constructor for a class X is a constructor of class X for which each parameter that is not a function parameter pack has a default argument (including the case of a constructor with no parameters).
If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted ([dcl.fct.def]).
An implicitly-declared default constructor is an inline public member of its class.


1) It doesn't matter if it is a constructor with or without parameters, see wording of [class.default.ctor]/1.

YSC
  • 38,212
  • 9
  • 96
  • 149