Replacing a vector with a list of initializers

i has std::vector<std::vector<double>> and would like to add some elements at the end of this, so this was my test:

 std::vector<std::vector<double> > vec; vec.emplace_back({0,0}); 

but this does not compile, whereas the following:

 std::vector<double> vector({0,0}); 

Why can't emplace_back create an element at this position? Or what am I doing wrong?

Thank you for your help.

+13
c ++ emplace
source share
3 answers

Calculation of the pattern cannot guess that the parenthesized initialization list must be a vector. You must be explicit:

 vec.emplace_back(std::vector<double>{0.,0.}); 

Note that this creates a vector, and then moves it to a new element using the std::vector copy move constructor. So in this particular case, it has no advantage over push_back() . @TimKuipers answer shows a way around this problem.

+8
source share

In the previous answer, you can get the code to compile when you construct a vector in a string and replace it. This means, however, that you call the move constructor on a temporary vector, which means that you are not creating the vector in place, whereas the whole reason for using emplace_back , not push_back .

Instead, you should list the initializers list in initializer_list , for example:

 #include <vector> #include <initializer_list> int main() { std::vector<std::vector<int>> vec; vec.emplace_back((std::initializer_list<int>){1,2}); } 
+17
source share

The constructor std::vector<double> can use the int curly list for its constructor std::vector<double>(std::initializer_list<double>) .

emplace_back() cannot emplace_back() element from the curly brackets expression because it is a template that uses perfect forwarding. The standard prevents the compiler from inferring the type {0,0} , so std::vector<double>::emplace_back<std::initializer_list<double>>(std::initializer_list<double>) does not compile for emplace_back({}) .

Another answer indicates that emplace_back can be compiled for an argument of type std::initializer_list<T> if it should not infer the type directly from the expression {} . As an alternative to casting an argument to emplace_back , you can first emplace_back argument. As stated in clause 30 of Meyers (Effective Modern C ++), auto allowed to display the type of curly bracket expression, and with perfect transfer, it is the type of object whose type was deduced by auto .

 std::vector<std::vector<double> > vec; auto int_list = {0, 0}; // int_list is type std::initializer_list<int> vec.emplace_back(int_list); // instantiates vec.emplace_back<std::initializer_list<int>> 

emplace_back adds an element to vec by calling std::vector<double>(std::forward<std::initializer_list<int>>(int_list)) , which calls std::vector<double>(std::initializer_list<double>) constructor and int_list elements int_list converted.

0
source share

All Articles