问题
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