3
votes

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

1
You only get aggregate initialization when your class is an aggregate. To know when that is, see: en.cppreference.com/w/cpp/language/aggregate_initializationNathanOliver
Sooo add protected: A(int i, int k) : i(i),k(k){}?KamilCuk
@KamilCuk I don't like it cause 1) I have to write it :-) 2) I won't be able to use {i,k} anymore, only A(i,k) (DOESN'T APPLY)Bill Kotsias
I won't be able to use {i,k} you should be able to.KamilCuk
@KamilCuk You're right! onlinegdb.com/HygVRYgGRD So, only (1) stands (laziness - which IMHO was the purpose of {} init... but anyway)Bill Kotsias

1 Answers

4
votes

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.