6

我想std::vector用一些元素构造一个,这些元素由某个特定的构造函数而不是默认构造函数构造。换句话说,我想在构建向量时放置元素。我怎样才能做到这一点?

考虑一下

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.
4

2 回答 2

5

您的Item班级不支持复制或移动。这将阻止大多数操作std::vector编译,包括std::vector::reservestd::vector::resize。如果你真的有这样的课程,你可能想要一个std::vector<std::aligned_storage_t<sizeof(Item), alignof(Item)>>

如果您可以向 中添加移动构造函数Item,则可以改为创建辅助函数(因为您使用的构造函数重载是根据复制定义的)。请注意,以下版本仅适用于一元构造函数。

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

用法:

auto vec = make_vector<Item>(10, 3.14);
于 2017-10-11T10:53:10.773 回答
5

您可以使用带有两个迭代器的向量构造函数。例如,您可以使用来自vector<double>.

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

现场演示

或者您可以编写自己的自定义迭代器类来进行初始化:

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

现场演示

于 2017-10-11T11:17:04.677 回答