Reputation: 33579
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.
Upvotes: 14
Views: 1692
Reputation: 109089
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.
For a C++11 compiler, you must either remove the initializer, which will make Foo
an aggregate, or provide a two argument constructor.
Upvotes: 9
Reputation: 33046
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, [](){} });
}
Upvotes: 14