Can I use the C++11 brace initialization syntax to avoid declaring trivial constructors for simple aggregates?
Asked Answered
A

2

14

Let's say I have the following code:

#include <vector>

struct Foo
{
    int tag = 0;
    std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
}

And now I want to add a new Foo item to the vector with the specific tag and code without explicitly creating a temporary. That means I must add a constructor for Foo:

struct Foo
{
    inline Foo(int t, std::function<void ()> c): tag(t), code(c) {}

    int tag = 0;
    std::function<void ()> code;
};

And now I can use emplace_back:

v.emplace_back(0, [](){});

But when I had to do this again - for the 100th time - with a newly created struct, I thought: can't I use the brace initializer? Like so:

#include <vector>

struct Foo
{
   int tag = 0;
   std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
   v.push_back(Foo{ 0, [](){} });
}

That gives me a compilation error (cannot convert from 'initializer-list' to 'Foo'), but I hope this can be done and I've just got the syntax wrong.

Aggrade answered 7/6, 2015 at 17:38 Comment(0)
C
14

In C++11, you can't use an aggregate initializer with your struct because you used an equal initializer for the non-static member tag. Remove the = 0 part and it will work:

#include <vector>
#include <functional>

struct Foo
{
   int tag;
   std::function<void ()> code;
};

int main()
{
   std::vector<Foo> v;
   v.push_back(Foo{ 0, [](){} });
}
Cerous answered 7/6, 2015 at 17:44 Comment(2)
Note this changes in C++14, where Foo is an aggregate and can be initialized using aggregate initialization.Pilsudski
Wow, that's totally unexpected. Thanks!Aggrade
T
9

According to the C++11 standard, Foo is not an aggregate, the presence of the brace-or-equal-initializer prevents it from being one.

However, this rule was changed for C++14, so if you compile your code with -std=c++14 (or whatever your compiler's equivalent setting is), Foo will be an aggregate, and your code will compile successfully.

Live demo

For a C++11 compiler, you must either remove the initializer, which will make Foo an aggregate, or provide a two argument constructor.

Tuesday answered 7/6, 2015 at 17:47 Comment(1)
Gotta wait for Visual Studio 2015 for C++14 support :)Aggrade

© 2022 - 2024 — McMap. All rights reserved.