How to emplace elements while constructing std::vector?

天大地大妈咪最大 提交于 2020-01-24 09:29:09

问题


I want to construct an std::vector with some elements having these elements constructed by some particular constructor rather than the default constructor. In other words I want to emplace the elements while constructing the vector. How can I do that?

Consider this:

struct Item
{
    Item(double) {}
    Item(const Item&) = delete;
    Item(Item&&) = delete;
};
std::vector<Item> vv(10, 3.14); // Fails! Tries to copy while I want to emplace.

回答1:


Your Item class doesn't support copies nor moves. This will prevent most operations on std::vector from compiling, including std::vector::reserve and std::vector::resize. If you really have such a class, you might want an std::vector<std::aligned_storage_t<sizeof(Item), alignof(Item)>> instead.

If you can add a move constructor to Item, you can create your helper function instead (as the constructor overload that you're using is defined in terms of copying). Note that the version below only works for unary constructors.

template <typename T, typename Arg>
auto make_vector(std::size_t n, Arg&& arg)
{
    std::vector<T> result;
    result.reserve(n);

    for(std::size_t i = 0; i < n; ++i)
        result.emplace_back(arg);

    return result;
}

Usage:

auto vec = make_vector<Item>(10, 3.14);



回答2:


You can use the vector constructor that takes two iterators. For example you could use iterators from a vector<double>.

std::vector<double> init(10, 3.14);
std::vector<Item> vv(init.begin(), init.end());

Live demo.

Or you could write your own custom iterator class to do the initialization:

struct ItemInitializer {
  int index;
  double value;

  using value_type = double;
  using difference_type = int;  
  using pointer = const double*;
  using reference = const double&;
  using iterator_category = std::forward_iterator_tag;

  ItemInitializer() : index(0), value(0.0) {}
  ItemInitializer(int index, double v = 0.0) : index(index), value(v) {}

  bool             operator!=(const ItemInitializer& other) const { return other.index != index; }
  ItemInitializer& operator++() { index++; return *this; }
  ItemInitializer  operator++(int) { ItemInitializer ret(index, value); index++; return ret; }
  const double&    operator*() const { return value; }  
  const double*    operator->() const { return &value; } 
};

std::vector<Item> vv(ItemInitializer{0, 3.14}, ItemInitializer{10});

Live demo.



来源:https://stackoverflow.com/questions/46686258/how-to-emplace-elements-while-constructing-stdvector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!