samedi 15 janvier 2022

Why can't I use an arbitrary nesting of braces to construct most classes?

Given the following code:

struct A;

struct B {
    B() {}
    B(A &&) {}
};

struct A {
    A() {}
    A(B &&) {}
};

Then I can use as many braces as I want to construct A or B.

// default construct A
auto a = A{};
// default construct B, forward to A
auto b = A;
// default construct A, forward to B, forward to A
auto c = A};
// etc.
auto d = A}};
auto e = A}}};

Similarly, given

struct C {
    C(std::initializer_list<C>) {}
};

then I can also use as many braces as I want

// default construct C
auto f = C{};
// construct from initializer_list of one default constructed C
auto g = C;
// construct from initializer_list of one C constructed from empty initializer_list
auto h = C};
// etc.
auto i = C}};
auto j = C}}};

Why doesn't the same argument work for a truly boring type?

struct D {
};

or, rewritten for clarity:

struct D {
    D() {}
    D(D &&) {}
};

This fails even on

auto k = D;

Why does this not default construct a D with the innermost braces, and then pass that rvalue on to the move constructor of D?

See it live: https://godbolt.org/z/E763EPGh1

Aucun commentaire:

Enregistrer un commentaire