QByteArray 的标准替代品
Standard replacement for QByteArray
我想将 Qt C++11 函数移植到标准 C++11。该函数有一个 QByteArray
参数,它接受任何类型的数据(文本、二进制数据等)并根据数据计算哈希值。
QByteArray
似乎很适合,因为它可以携带任何类型的数据,并且有很多功能可以从流、设备、字符串等中填充它。它甚至可以包装数据无需使用 fromRawData()
.
进行深度复制
是否有提供类似灵活性的标准 C++11 解决方案?目前我倾向于使用旧的 void*
加大码。
我不知道这种标准容器具有与 QByteArray 相同的复杂功能,但我会从 std::vector< char >
开始,并围绕它实现一个带有缺失和必要功能的包装器。
std::vector
具有很高的灵活性,您可以在常数时间内访问每个元素,并且可以轻松地将其转换为std::string(例如Converting a vector to string)。
如果插入操作比较重要,也许你可以试试std::list< char >
。主要是链表实现。
根据 Jesper Juhl 的评论:使用 uint8_t
作为模板参数将描述真实的 字节数组 行为。
不是很标准,但您可以使用 view
/span
classes from the Guideline Support Library(它最终应该会成为标准)来模拟 fromRawData
。
当然,这不涉及与共享所有权相关的生命周期问题,但在您的情况下可能就足够了。
此外,虽然它可能不是所有组件的要求,但 GSL 被宣传为基于 C++14。
Is there a standard C++11 solution that provides similar flexibility? Currently I tend to use good old 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));
}
我想将 Qt C++11 函数移植到标准 C++11。该函数有一个 QByteArray
参数,它接受任何类型的数据(文本、二进制数据等)并根据数据计算哈希值。
QByteArray
似乎很适合,因为它可以携带任何类型的数据,并且有很多功能可以从流、设备、字符串等中填充它。它甚至可以包装数据无需使用 fromRawData()
.
是否有提供类似灵活性的标准 C++11 解决方案?目前我倾向于使用旧的 void*
加大码。
我不知道这种标准容器具有与 QByteArray 相同的复杂功能,但我会从 std::vector< char >
开始,并围绕它实现一个带有缺失和必要功能的包装器。
std::vector
具有很高的灵活性,您可以在常数时间内访问每个元素,并且可以轻松地将其转换为std::string(例如Converting a vector to string)。
如果插入操作比较重要,也许你可以试试std::list< char >
。主要是链表实现。
根据 Jesper Juhl 的评论:使用 uint8_t
作为模板参数将描述真实的 字节数组 行为。
不是很标准,但您可以使用 view
/span
classes from the Guideline Support Library(它最终应该会成为标准)来模拟 fromRawData
。
当然,这不涉及与共享所有权相关的生命周期问题,但在您的情况下可能就足够了。
此外,虽然它可能不是所有组件的要求,但 GSL 被宣传为基于 C++14。
Is there a standard C++11 solution that provides similar flexibility? Currently I tend to use good old 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));
}