Любая альтернатива std :: dynarray в настоящее время доступна?

C ++ 11 дал нам здорово std::array, который требует, чтобы размер был известен во время компиляции:

std::array<int, 3> myarray = {1, 2, 3};

Теперь у меня есть некоторые старые short* буферы для переноса, размер которых будет известен (и, конечно, будет) только во время выполнения.

C ++ 14 определит std::dynarray чтобы покрыть это дело, но dynarray пока недоступен ни в GCC 4.7, ни в Clang 3.2.

Итак, кто-нибудь знает контейнер, который сопоставим с std::array (с точки зрения эффективности), но не требует указывать размер во время компиляции? Я подозреваю, что у Буста кое-что готово для меня, хотя я не мог ничего найти.

15

Решение

Вы могли бы (ab) использовать std::valarray<short>,

int main() {
short* raw_array = (short*) malloc(12 * sizeof(short));
size_t length = 12;
for (size_t i = 0; i < length; ++ i) {
raw_array[i] = (short) i;
}

// ...

std::valarray<short> dyn_array (raw_array, length);
for (short elem : dyn_array) {
std::cout << elem << std::endl;
}

// ...

free(raw_array);
}

valarray поддерживает большинство функций dynarray, Кроме:

  • распределитель
  • обратный итератор
  • .at()
  • .data()

Обратите внимание, что стандарт (по состоянию на n3690) не требует valarray хранение должно быть непрерывным, хотя нет причин не делать этого :).

(Для некоторых деталей реализации в libstdc ++ он реализован как пара (длина, данные), а в libc ++ он реализован как (начало, конец).)

4

Другие решения

Я думаю std::vector это то, что вы ищете раньше dynarray становится доступным. Просто используйте конструктор выделения или reserve и вы избежите перераспределения накладных расходов.

17

Я проголосую за std::unique_ptr<short[]>(new short[n]) если вам не нужен доступ с проверкой диапазона, предоставляемый std::dynarray<T>::at(), Вы даже можете использовать список инициализатора:

#include <iostream>
#include <memory>

int main(int argc, char** argv) {
const size_t n = 3;
std::unique_ptr<short[]> myarray(new short[n]{ 1, 2, 3 });
for (size_t i = 0; i < n; ++i)
std::cout << myarray[i] << '\n';
}
10

Буфер и размер, а также некоторые основные методы дают вам большую часть того, что вы хотите.

Много шаблонного, но как то так:

template<typename T>
struct fixed_buffer {
typedef       T                               value_type;
typedef       T&                              reference;
typedef const T&                              const_reference;
typedef       T*                              iterator;
typedef const T*                              const_iterator;
typedef std::reverse_iterator<iterator>       reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef size_t                                size_type;
typedef ptrdiff_t                             difference_type;

std::size_t length;
std::unique_ptr<T[]> buffer;

std::size_t size() const { return length; }

iterator begin() { return data(); }
const_iterator begin() const { return data(); }
const_iterator cbegin() const { return data(); }
iterator end() { return data()+size(); }
const_iterator end() const { return data()+size(); }
const_iterator cend() const { return data()+size(); }

reverse_iterator rbegin() { return {end()}; }
const_reverse_iterator rbegin() const { return {end()}; }
const_reverse_iterator crbegin() const { return {end()}; }
reverse_iterator rend() { return {begin()}; }
const_reverse_iterator rend() const { return {begin()}; }
const_reverse_iterator crend() const { return {begin()}; }

T& front() { return *begin(); }
T const& front() const { return *begin(); }
T& back() { return *(begin()+size()-1); }
T const& back() const { return *(begin()+size()-1); }
T* data() { return buffer.get(); }
T const* data() const { return buffer.get(); }
T& operator[]( std::size_t i ) { return data()[i]; }
T const& operator[]( std::size_t i ) const { return data()[i]; }
fixed_buffer& operator=(fixed_buffer &&) = default;
fixed_buffer(fixed_buffer &&) = default;

explicit fixed_buffer(std::size_t N):length(N), buffer( new T[length] ) {}
fixed_buffer():length(0), buffer() {}

fixed_buffer(fixed_buffer const& o):length(o.N), buffer( new T[length] )
{
std::copy( o.begin(), o.end(), begin() );
}
fixed_buffer& operator=(fixed_buffer const& o)
{
std::unique_ptr<T[]> tmp( new T[o.length] );
std::copy( o.begin(), o.end(), tmp.get() );
length = o.length;
buffer = std::move(tmp);
return *this;
}
};

at() отсутствует, как и распределители.

operator= отличается от dyn_array предложение — предложение блоков operator=Даю ей значение семантики. Несколько методов менее эффективны (например, copy строительство). Даю пустой fixed_buffer,

Это, вероятно, заблокировало бы возможность использовать стек для хранения dyn_arrayНаверное, поэтому не позволяет. Просто удали мой operator= и тривиальный конструктор, если вы хотите поведение, близкое к dyn_array.

4

C ++ 14 также добавляет массивы переменной длины, аналогичные массивам в C99, и это уже поддерживается некоторыми компиляторами:

void foo(int n) {
int data[n];
// ...
}

Это не контейнер, так как он не поддерживает begin() а также end() и т. д., но может быть осуществимым решением.

0

dynarray очень легко реализовать себя без компонента выделения стека, что, по-видимому, невозможно сделать до возможно C ++ 14 в любом случае — так что я просто бросил dynarray inverse-backport (forwardport?) как часть моей библиотеки и начал использовать его с тех пор. Работает в C ++ 03 без каких-либо предложений «void in Nebraska», так как это абсолютно не зависит от какой-либо специфической для C ++ 11 возможности, и это очень удобно иметь
Таким образом, когда C ++ 1y / 2z dynarray приходит мой код по-прежнему по большей части совместим.

(Это также одна из многих очевидных вещей «почему в С ++ такого не было раньше?», Так что хорошо бы иметь это рядом).

Это было до того, как я узнал, что, по-видимому, C ++ 1y-dynarray и C ++ 1y-runtime-size-массивы — это то же самое предложение (одно — просто синтаксический сахар для другого), а не два разных, но дополняющих предложения, как я сначала подумал. Так что если бы мне пришлось сейчас решать тот же вопрос, я бы наверное переключитесь на что-то основанное на решении @ Yakk для корректности.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector