初始化向量的高效而优雅的方法
Efficient and elegant way to initialize vector
给定以下 C++14 代码:
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) };
我知道 initializer_list 中的 A
被 复制 到向量中,而不是被 移动(在Whosebug中有很多关于这个的问题)。
我的问题是:如何将它们移动到向量中?
我只能做丑陋的 IIFE(保持 v
常量)并且只是避免 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;
}();
是否有可能使这种优雅的和高效?
PD: v
必须 是 std::vector<A>
供以后使用
不确定它是否算作 "elegant",但您可以使用一个数组(或 std::array
),它使用不会遇到此问题的聚合初始化和 move_iterator
来移动将值放入 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())};
你问了一个 C++14 解决方案,所以你可以使用带有 auto
个参数的可变 lambda 函数。
按照您的 lambda 函数示例...
#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));
}
如果您更喜欢旧类型(非 lambda)函数,或者您想要一个也适用于 C++11 的解决方案,getVA
可以如下编写
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;
}
给定以下 C++14 代码:
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) };
我知道 initializer_list 中的 A
被 复制 到向量中,而不是被 移动(在Whosebug中有很多关于这个的问题)。
我的问题是:如何将它们移动到向量中?
我只能做丑陋的 IIFE(保持 v
常量)并且只是避免 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;
}();
是否有可能使这种优雅的和高效?
PD: v
必须 是 std::vector<A>
供以后使用
不确定它是否算作 "elegant",但您可以使用一个数组(或 std::array
),它使用不会遇到此问题的聚合初始化和 move_iterator
来移动将值放入 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())};
你问了一个 C++14 解决方案,所以你可以使用带有 auto
个参数的可变 lambda 函数。
按照您的 lambda 函数示例...
#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));
}
如果您更喜欢旧类型(非 lambda)函数,或者您想要一个也适用于 C++11 的解决方案,getVA
可以如下编写
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;
}