Вектор C ++ с фиксированной емкостью после инициализации - PullRequest
0 голосов
/ 26 декабря 2018

Мне нужен контейнер 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 };
};

Мои вопросы:

  • Зачем мне это делать вручную?Я не мог найти стандартный контейнер.А может я не посмотрел в нужном месте?Или потому, что я пытаюсь сделать что-то необычное?
  • Правильно ли реализован рукописный контейнер?Как насчет безопасности исключений, безопасности памяти и т. Д.?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...