Question

If all of your class/struct data members lack initializers, you can use uniform initialization syntax to construct the object.

struct foo
{
    int i;
    float f;
};
...
foo bar{ 5, 3.141f };

But if one or more members have initializers, uniform initialization syntax becomes invalid.

struct foo
{
    int i;
    float f = 0;
};
...
foo bar{ 5, 3.141f };  // Compiler error.

I surmise that the addition of a data member initializer automatically implements one or more default constructors and suppresses the default implementation of the initialization_list constructor. Is that the intended standard? Why does it work this way?

Was it helpful?

Solution

Yes, this is intended by the standard. What you are attempting here is aggregate initialization. Unfortunately, your second foo is no longer considered an aggregate due to the equal initializer of f. See 8.5.1 [dcl.init.aggr] (emphasis mine):

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equalinitializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

Because you have an equal initializer for the member f, you will need to provide a custom constructor to support the syntax you are after:

struct foo
{
  int i;
  float f = 0;
  constexpr foo(int i, float f) : i(i), f(f) { }
};
...
foo bar{ 5, 3.141f }; // now okay

As to why this was specified in the standard, I have no idea.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top