P1008 ("Prohibit aggregates with user-declared constructors") has become part of the C++20 standard, in order to prevent surprising behavior when using aggregate initialization:
struct X {
int i{42};
X() = delete;
};
int main() {
X x2{3}; // Compiles in C++17, error in C++20
}
I agree that the above X x2{3};
statement should not compile. However, all the examples justifying P1008 that I've encountered are not realistic at all - they are purely syntactical and basically meaningless foo
/bar
/baz
code snippets.
What problem does P1008 solve in practice? I find it hard to imagine how I would end up writing something like the above X
in a real program.
Deleting the default constructor in a C++17 aggregate without providing other constructors to initialize it seems unrealistic to me.
The most obvious case is this:
struct X
{
private:
X() = default;
};
X x{};
This is not a type which should be able to be initialized outside of a privately accessible context. But it can be.
Now, such types might seem silly, but they're actually useful for implementing private functions that work through forwarding functions. make_shared
for example cannot call constructors declared private
, even if you make the make_shared
template a friend. So instead, you make the constructors public
, but require that the user pass an instance of a type that can only be constructed by someone with private
access. So X
would either be a member type of the target class or X
would make the target class a friend
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With