Стандартная замена QByteArray

Я хочу перенести функцию Qt С++ 11 на стандартный С++ 11. Функция имеет параметр QByteArray, который принимает любые данные (текст, бинарные данные и т. д.) и вычисляет хэш из данных.

QByteArray кажется хорошо подходящим, потому что он может нести любые данные и имеет множество функций, которые позволяют заполнять их из потоков, устройств, строк и т. д. Он даже может оборачивать данные без глубокого копирования с помощью fromRawData().

Существует ли стандартное решение C++11, обеспечивающее аналогичную гибкость? В настоящее время я склоняюсь к старому доброму размеру void* plus size.


person Silicomancer    schedule 23.11.2016    source источник
comment
Практически любой контейнер STL может хранить массив символов (без знака).   -  person    schedule 24.11.2016
comment
@Raw N: Как можно инициализировать vector<unsigned char> из указателя и размера (или, может быть, строки C) без глубокого копирования?   -  person Silicomancer    schedule 24.11.2016
comment
myVector.assign(pointer, pointer + size) может быть? Также существует около 7 различных конструкторов.   -  person    schedule 24.11.2016
comment
@Silicomancer Если вам не нужна глубокая копия, используйте указатель и размер. Они у вас уже есть. Большинство стандартных библиотечных операций работают с диапазонами iterator, поэтому передача ptr, ptr+size в качестве диапазона очень распространена. Чтобы быть более прямым, нет ничего даже отдаленно близкого к широте функциональных возможностей, которые предлагает QByteArray. Большая часть этого потребует от вас реализации поведения.   -  person WhozCraig    schedule 24.11.2016
comment
@RawN ... копирует значение в диапазоне. Конкретный метод, упомянутый OP, был fromRawData, и нет ничего похожего его можно использовать через вектор, если вы не столкнетесь с серьезной перегрузкой std::allocator (и, честно говоря, это не стоило бы проблем).   -  person WhozCraig    schedule 24.11.2016
comment
std::vector<uint8_t> мне кажется очевидной заменой QByteArray, если вам просто нужен контейнер, который может хранить произвольные двоичные данные.   -  person Jesper Juhl    schedule 24.11.2016
comment
Надеюсь, мы получим std::array_view, и в данном случае это сработает. Прямо сейчас я думаю, что вы можете получить его как часть основной библиотеки руководств.   -  person NathanOliver    schedule 24.11.2016


Ответы (3)


Существует ли стандартное решение C++11, обеспечивающее аналогичную гибкость? В настоящее время я предпочитаю использовать старый добрый void* plus size.

Не существует стандартного решения C++11, которое предоставляет контейнер, который может управлять как собственной памятью, так и оборачивать память, управляемую кем-то другим.

Вы можете просто скопировать QByteArray (это несколько файлов) и связать их с вашим проектом, если позволяют условия лицензии.

В противном случае, если вы собираетесь работать только с контейнерами с непрерывным хранилищем для всех элементов, аргументы const void* и size_t имеют смысл и будут наиболее переносимыми и адаптируемыми. При необходимости вы можете предоставить удобные перегрузки. Например.

HashType calculateHash(const void*, size_t);

template <typename T> HashType calculateHash(const T& container) {
  static_assert(sizeof(typename T::value_type) == 1, "value_type must be byte-sized");
  assert(&container[container.size()-1] == &container[0]+container.size());
  return calculateHash(&container[0], container.size());
}

Для поддержки любого контейнера, даже с несмежным хранилищем, база calculateHash может принимать диапазон и предлагать перегрузку для хеширования всего контейнера.

template <typename I>
HashType calculateHash(I start, I const end) {
  HashType hash;
  for (; start != end; ++start)
    hash.update(*start);
  return hash;
}

template <typename C>
HashType calculateHash(const C& container) {
  using std::begin;
  using std::end;
  return calculateHash(begin(container), end(container));
}
person Kuba hasn't forgotten Monica    schedule 23.11.2016

Я не знаю такого стандартного контейнера, который имеет ту же сложную функциональность, что и QByteArray, но я бы начал с std::vector< char > и реализовал бы вокруг него оболочку с отсутствующими и необходимыми функциями.

std::vector обладает высокой гибкостью, вы можете получить доступ к каждому элементу за постоянное время и легко преобразовать его в std::string (например, Преобразование вектора в строку).

Если операция insert более важна, возможно, вы можете попробовать std::list< char >. В основном это реализация связанного списка.

Основываясь на комментарии Джеспера Юла: использование uint8_t в качестве аргумента шаблона описывает реальное поведение массива байтов.

person Tibor Takács    schedule 23.11.2016
comment
Но поддерживает ли он перенос данных без глубокого копирования? Если это не так, я не могу представить, как такая обертка могла это сделать. - person Silicomancer; 24.11.2016
comment
С помощью итераторов или оператора [] вы можете получить доступ к элементу без глубокого копирования. - person Tibor Takács; 24.11.2016
comment
@TiborTakács Он имеет в виду возможность имитировать fromRawData< /a> функциональность. - person WhozCraig; 24.11.2016
comment
char будет плохим аргументом шаблона для вектора, так как вы не знаете, подписан он или нет в разных реализациях (в C++ существует 3 типов символов; char, unsigned char и signed char, и все они разные типов к системе типов, а подписанность char определяется реализацией (да, это укусило меня)). Лучше быть конкретным и использовать uint8_t в этом случае (ИМХО). - person Jesper Juhl; 24.11.2016
comment
@Jesper Juhl Я мог бы согласиться, сначала я тоже думал использовать uint8_t, но QByteArray использует char, поэтому я подумал, что аргумент шаблона char больше подходит для исходного поведения. - person Tibor Takács; 24.11.2016
comment
@Tibor Takács Я знаю, что QByteArray использует char - я считаю это (наряду со многими другими вещами) ошибкой со стороны разработчиков Qt. - person Jesper Juhl; 24.11.2016
comment
@Jesper Juhl: добавлено к ответу. - person Tibor Takács; 24.11.2016

Не совсем стандартно, но вы можете использовать view/span классы из библиотеки поддержки рекомендаций (которая со временем должна стать стандартной) для эмуляции fromRawData.

Конечно, это не относится к проблемам жизненного цикла, связанным с совместным владением, но в ваших случаях этого может быть достаточно.

Кроме того, хотя это может быть требованием не для всех компонентов, GSL рекламируется как основанный на C++14.

person Nobody moving away from SE    schedule 23.11.2016