高效优雅的初始化矢量方式

时间:2017-04-28 09:40:41

标签: c++ c++14 move initializer-list

给出以下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) };

我知道初始化列表中的A复制到了向量中,而不是被移动(有很多问题)在stackoverflow中关于这个)。

我的问题是:我如何移动到矢量中?

我只能做丑陋的IIFE(保持v const)并且只是避免使用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>以供日后使用

2 个答案:

答案 0 :(得分:7)

不确定它是否算作&#34;优雅&#34;但是你可以使用一个数组(或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

答案 1 :(得分:2)

你问一个C ++ 14解决方案,所以你可以使用带有auto参数的variadic 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;
 }