Инициализация массивов статического размера для типов без конструктора по умолчанию - PullRequest
0 голосов
/ 19 ноября 2018

Я кодирую простой шаблонный кольцевой буфер:

template <typename T, size_t N>
class CircularBuffer {

    T      _buf[N];
    T     *_data;
    size_t _head;
    size_t _count;
    size_t _capacity;

    CircularBuffer():
            _data(nullptr),
            _head(0),
            _count(0),
            _capacity(N) {}

protected:

    T* buffer() {
        if (_count <= N) return &_buf;
        else return _data;
    }

public:

    T& operator[](size_t i) {
        size_t j = i % _count;
        j = (_head + j) % _capacity;
        return buffer()[j];
    }

    T& push_back(const T& o) {
        if (_count == _capacity) {
            dynamically_allocate_data();
        }
        size_t j = (_head + _count++) % _capcity;
        buffer()[j] = o;
    }

    T pop_front() {
        size_t old_head = _head;
        _head = (_head + 1) % _capacity;
        return buffer()[old_head];
    }

};

Это урезано от реальной вещи, но это не за горами, и вы поняли идею.Это позволяет избежать выделения памяти для буферов менее чем N элементов.

Проблема заключается в том, что это не работает для T, которые не имеют конструкторов по умолчанию.Я мог бы предоставить конструктор для CircularBuffer - ala std::vector s -, который принимает T для заполнения пустого буфера, но я не уверен, как на самом деле реализовать это, не вызывая неявно TКонструктор по умолчанию (возможно, не существующий).

В ответах на аналогичные вопросы предлагается использовать std::vector или размещение нового в массиве void*, но в этом случае это не относится, поскольку весь смысл заключается вИзбегайте динамического выделения памяти во внутреннем цикле.

Как я могу построить этот класс для T без конструкторов по умолчанию?(Или, альтернативно, есть ли другая схема, которая позволит избежать необходимости создания пустого T в буфере для начала?)

1 Ответ

0 голосов
/ 19 ноября 2018

Как насчет использования std::optional (или boost::optional, если ваш компилятор до 17 лет)?Вы можете определить статический массив как std::optional<T> _buf[N];.

. Тип std::optional поддерживает конструкцию размещения (поэтому T не нужен конструктор по умолчанию) и размещается статически, что отвечает вашим требованиям.не так ли?

...