Ниже вы найдете строковый литерал constexpr для вычисления CRC32.Альтернатива reinterpret_cast с функциями constexpr
Мне пришлось переосмыслить строковый литерал от char
до unsigned char
. Поскольку reinterpret_cast
недоступен в функции constexpr, обходной путь представляет собой небольшую полезную функцию для дополнения Two вручную, но я немного разочарован этим.
Существует ли более элегантное решение для борьбы с подобными манипуляциями?
#include <iostream>
class Crc32Gen {
uint32_t m_[256] {};
static constexpr unsigned char reinterpret_cast_schar_to_uchar(char v) {
return v>=0 ? v : ~(v-1);
}
public:
// algorithm from http://create.stephan-brumme.com/crc32/#sarwate
constexpr Crc32Gen() {
constexpr uint32_t polynomial = 0xEDB88320;
for (unsigned int i = 0; i <= 0xFF; i++) {
uint32_t crc = i;
for (unsigned int j = 0; j < 8; j++)
crc = (crc >> 1)^(-int(crc & 1) & polynomial);
m_[i] = crc;
}
}
constexpr uint32_t operator()(const char* data) const {
uint32_t crc = ~0;
while (auto c = reinterpret_cast_schar_to_uchar(*data++))
crc = (crc >> 8)^m_[(crc & 0xFF)^c];
return ~crc;
}
};
constexpr Crc32Gen const crc32Gen_;
int main() {
constexpr auto const val = crc32Gen_("The character code for É is greater than 127");
std::cout << std::hex << val << std::endl;
}
Редактировать: в этом случае static_cast<unsigned char>(*data++)
достаточно.
дополнительный аргумент, чтобы найти альтернативное решение. Даже если я вряд ли буду иметь дело с процессором, не использующим представление дополнений 2. – galop1n
Думая об этом, я могу просто добавить 128 символов и безопасно индексировать в 'm_'. – galop1n
@ galop1n вы можете просто отличить от 'char' до' unsigned char' - см. Выше. – ecatmur