简体   繁体   中英

Why doesn't my compiler recognise “Bond() = default;”?

Please look at this code

class Bond
{
    public:
        Bond(int payments_per_year, int period_lengths_in_months);
        Bond() = default;

    private:
        const int payments_per_year;
        const int period_length_in_months;
    };

int main()
{
    Bond b; // Error here
}

When attempting to compile I get an error:

error C2280: 'Bond::Bond(void)': attempting to reference a deleted function".

It's not a "rule of 3" violation since I've added the default constructor back.

Why doesn't the compiler recognise Bond() = default; ?

The default constructor is suppressed since there are constant members that need to be explicitly initialised.

Therefore, due to that suppression, writing Bond() = default does not reintroduce the default constructor.

(You can see this effect by removing all the constructors in the class - you still can't instantiate a b .)

If you drop the const from the members then all will be well; although another alternative is to supply a brace-or-equal-initializer for each const member;

const int payments_per_year = 2;
const int period_length_in_months = 6;

for example.

You are being affected by section [class.default.ctor]p2 of the draft C++ standard (or [class.ctor]p5 in C++11) which says:

A defaulted default constructor for class X is defined as deleted if:
...
- any non-variant non-static data member of const-qualified type (or array thereof) with no brace-or-equal-initializer does not have a user-provided default constructor,
...

They possible key to fixing your issue is with the phrase with no brace-or-equal-initializer so if you provide brace-or-equal-initializer that will fix your issue eg:

const int payments_per_year{12};
const int period_length_in_months{48};

brace-or-equal-initializer does not require braces, we can see this the grammar:

brace-or-equal-initializer:
    = initializer-clause
    braced-init-list

but using uniform initialization has some advantages such as making narrowing conversions ill-formed that it is worth getting used to using them.

Both gcc and clang provide more meaningful diagnostics for this see the live godbolt session . Sometimes it can be helpful to try your code on multiple compilers, especially if you have a minimal test case like this eg clang says:

 warning: explicitly defaulted default constructor is implicitly deleted [-Wdefaulted-function-deleted]
    Bond() = default;
    ^
 note: default constructor of 'Bond' is implicitly deleted because field 'payments_per_year' of const-qualified type 'const int' would not be initialized
    const int payments_per_year;
              ^
...

Another fix, is to specify a default value in the declaration of the constants:

const int payments_per_year = {12};

This can still be overridden by the valued constructor, but allows the default constructor to proceed.

This is also a very flexible way to simplify your multiple constructor cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM