c++default-constructorrule-of-zero

Rule of zero - default constructor not generated


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"?


Solution

  • 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.