Мне нужен контейнер C ++ со следующими требованиями:
- Контейнер может хранить не непрерывные и неподвижные объекты в непрерывной памяти.Для
std::vector
объект должен быть либо копируемым, либо подвижным. - Контейнер
capacity
известен во время строительства во время выполнения и фиксируется до уничтожения.Все необходимое пространство памяти выделяется при строительстве.Для boost::static_vector
емкость известна во время компиляции. - Размер контейнера может увеличиваться со временем, когда
emplace_back
больше элементов в контейнере, но никогда не должно превышать capacity
. - Поскольку объект не является копируемым или перемещаемым, перераспределение не допускается.
Похоже, что ни STL, ни BOOST не имеют нужный мне тип контейнера.Я также искал в этой стороне, но не нашел ответа.Итак, я реализовал один.
#include <memory>
template<class T>
class FixedCapacityVector {
private:
using StorageType = std::aligned_storage_t<sizeof(T), alignof(T)>;
static_assert(sizeof(StorageType) == sizeof(T));
public:
FixedCapacityVector(FixedCapacityVector const&) = delete;
FixedCapacityVector& operator=(FixedCapacityVector const&) = delete;
FixedCapacityVector(size_t capacity = 0):
capacity_{ capacity },
data_{ std::make_unique<StorageType[]>(capacity) }
{ }
~FixedCapacityVector()
{
for (size_t i = 0; i < size_; i++)
reinterpret_cast<T&>(data_[i]).~T();
}
template<class... Args>
T& emplace_back(Args&&... args)
{
if (size_ == capacity_)
throw std::bad_alloc{};
new (&data_[size_]) T{ std::forward<Args>(args)... };
return reinterpret_cast<T&>(data_[size_++]);
}
T& operator[](size_t i)
{ return reinterpret_cast<T&>(data_[i]); }
T const& operator[](size_t i) const
{ return reinterpret_cast<T const&>(data_[i]); }
size_t size() const { return size_; }
size_t capacity() const { return capacity_; }
T* data() { return reinterpret_cast<T*>(data_.get()); }
T const* data() const { return reinterpret_cast<T const*>(data_.get()); }
private:
size_t const capacity_;
std::unique_ptr<StorageType[]> const data_;
size_t size_{ 0 };
};
Мои вопросы:
- Зачем мне это делать вручную?Я не мог найти стандартный контейнер.А может я не посмотрел в нужном месте?Или потому, что я пытаюсь сделать что-то необычное?
- Правильно ли реализован рукописный контейнер?Как насчет безопасности исключений, безопасности памяти и т. Д.?