Reputation: 3358
I always thought that aggregate initialization was to save coders from writing custom constructors. However, this seems to have "sneaked in" a "security by-pass" for private constructors.
Say I have class A
which I only want to be created by class B
.
struct A
{
friend class B;
const int i, k;
private:
A () = default;
};
class B
{
public:
A what () { return {1, 2}; }
};
int main ()
{
B b {};
A a {2,3}; // oh no
return 0;
}
Above example compiles and runs fine, and through the use of braces I can very easily create an A
object anywhere.
The only way to prevent this is to write a user constructor, which then cancels out aggregate initialization altogether.
So my question is: is aggregate initialization a "hidden" constructor that is by default public
?
Live example: https://onlinegdb.com/r1jHLxzRD
Similar question with no answer: Private aggregate initialization
Upvotes: 5
Views: 556
Reputation: 96033
Since C++20 this type is no longer an aggregate, so this program no longer compiles.
Manually adding any constructor to a class now prevents it from being an aggregate.
Upvotes: 1
Reputation: 954
You can portably disable aggregate initialization by making the default constructor explicit
:
explicit A () = default;
This works on C++11, C++14, C++17, C++20, and C++23.
Upvotes: 0
Reputation: 238301
I always thought that aggregate initialization was to save coders from writing custom constructors.
That's something that aggregate initialisation achieves, but defining that as the purpose of aggregate initialisation is overly reductive.
However, this seems to have "sneaked in" a "security by-pass" for private constructors.
This sneaky case of aggregates with private (or even deleted!) default constructor was introduced in C++11 through introduction of defaulted (and deleted) member functions. It no longer exits in C++20 where A
is no longer an aggregate.
So my question is: is aggregate initialization a "hidden" constructor
I would describe aggregate initialisation as not using a constructor at all. Instead, members are initialised directly.
Upvotes: 5