Given the following C++14 code:
struct A { /* heavy class, copyable and movable */ };
// complex code to create an A
A f(int);
A g(int);
A h(int);
const std::vector<A> v = { f(1), g(2), h(3) };
I know the A
's in the initializer_list are copied into the vector, instead of being moved (there are a lot of questions in stackoverflow about this).
My question is: how can I move them into the vector?
I've only been able to do the ugly IIFE (that keeps v
const) and just avoids initializer_list:
const std::vector<A> v = []()
{
std::vector<A> tmp;
tmp.reserve(3);
tmp.push_back( f(1) );
tmp.push_back( g(2) );
tmp.push_back( h(3) );
return tmp;
}();
Is it possible to make this elegant and efficient?
PD: v
has to be a std::vector<A>
for later use
Not sure if it counts as "elegant" but you could use an array (or std::array
) which uses aggregate initialization that doesn't suffer from this problem and move_iterator
to move the values into the vector
.
std::array<A, 3> init = { f(1), g(2), h(3) };
std::vector<A> v{std::make_move_iterator(init.begin()),
std::make_move_iterator(init.end())};
Live demo.
You ask a C++14 solution, so you can use variadic lambda function with auto
arguments.
Following the example of your lambda function...
#include <vector>
struct A
{ };
A f (int) { return {}; }
A g (int) { return {}; }
A h (int) { return {}; }
int main ()
{
static const auto getVA = [](auto && ... args)
{
using unused = int[];
std::vector<A> ret;
ret.reserve(sizeof...(args));
(void)unused { 0,
(ret.emplace_back(std::forward<decltype(args)>(args)), 0)... };
return ret;
};
auto va = getVA(f(1), g(2), h(3));
}
If you prefer old type (not-lambda) function, or you want a solution that works also with C++11, getVA
can be written as follows
template <typename ... Args>
std::vector<A> const getVA (Args&& ... args)
{
using unused = int[];
std::vector<A> ret;
ret.reserve(sizeof...(args));
(void)unused { 0, (ret.emplace_back(std::forward<Args>(args)), 0)... };
return ret;
}
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