Everyone creates std::vector
from std::initializer_list
, but what about the other way around?
eg. if you use a std::initializer_list
as a parameter:
void someThing(std::initializer_list<int> items)
{
...
}
There are times when you have your items in a vector<T>
instead of a literal list:
std::vector<int> v;
// populate v with values
someThing(v); // boom! No viable conversion etc.
The more general question is: how to create an stl::initializer_list
from a STL iterable, not just std::vector
.
The answer is NO, you cannot do that.
An object of type std::initializer_list<T>
is a lightweight proxy object that provides access to an array of objects of type T. A std::initializer_list
object is automatically constructed when:
As far as library support goes, std::initializer_list
only has a default constructor that constructs an empty list, and its iterators are constant. The lack of a push_back()
member means you cannot apply e.g. a std::copy
with a std::back_inserter
iterator adaptor to fill it, and neither can you assign through such iterators directly:
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <vector>
int main()
{
auto v = std::vector<int> { 1, 2 };
std::initializer_list<int> i;
auto it = std::begin(i);
*it = begin(v); // error: read-only variable is not assignable
}
If you look at the Standard Containers, in addition to accepting std::initializer_list
in their constructors / inserters, they all have constructors / inserters taking an iterator pair, and the implementation is likely to delegate the initializer_list
function to the corresponding iterator pair function. E.g. the std::vector<T>::insert
function in libc++ is this simple one-liner:
iterator insert(const_iterator __position, initializer_list<value_type> __il)
{return insert(__position, __il.begin(), __il.end());}
You should modify your code along similar lines:
void someThing(std::initializer_list<int> items)
{
someThing(items.begin(), items.end()); // delegate
}
template<class It>
void someThing(It first, It last)
{
for (auto it = first, it != last; ++it) // do your thing
}
In times when you have your items in a vector instead of a literal list:
std::vector<int> v = { 1, 2 };
auto i = { 1, 2 };
someThing(begin(v), end(v)); // OK
someThing(i); // also OK
someThing({1, 2}); // even better