Jeff Wofford
Jeff Wofford

Reputation: 11547

Why do non-static data member initializers defeat uniform initialization syntax?

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?

Upvotes: 6

Views: 386

Answers (1)

marack
marack

Reputation: 2066

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.

Upvotes: 2

Related Questions