初始化向量的高效而优雅的方法

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())};

Live demo.

你问了一个 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;
 }