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.
If a type has a default constructor, either implicitly or explicitly declared, you can use brace initialization with empty braces to invoke it. For example, the following class may be initialized by using both empty and non-empty brace initialization: C++ Copy.
1 Answer. A constructor cannot specify any return type, not even void. A constructor cannot be final, static or abstract.
To customize how a class initializes its members, or to invoke functions when an object of your class is created, define a constructor. A constructor has the same name as the class and no return value. You can define as many overloaded constructors as needed to customize initialization in various ways.
Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.
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, [](){} });
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With