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