我想构造一个std::vector
,其中包含一些元素,这些元素由某些特定构造函数而不是默认构造函数构造。换句话说,我想在构造向量时对元素进行处理。我怎么能这样做?
考虑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.
答案 0 :(得分:6)
您的Item
课程不支持复制或移动。这样可以阻止std::vector
上的大多数操作进行编译,包括std::vector::reserve
和std::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);
答案 1 :(得分:3)
您可以使用带有两个迭代器的向量构造函数。例如,您可以使用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});