c++ - Alternative to reinterpret_cast with constexpr functions -
below, find constexpr string literal crc32 computation.
i had reinterpret string literal character char
unsigned char
. because reinterpret_cast
not available in constexpr function, workaround small utility function two's complement manually little disappointed it.
does exist more elegant solution deal kind of manipulation ?
#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 http://create.stephan-brumme.com/crc32/#sarwate constexpr crc32gen() { constexpr uint32_t polynomial = 0xedb88320; (unsigned int = 0; <= 0xff; i++) { uint32_t crc = i; (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 É greater 127" ); std::cout << std::hex << val << std::endl; }
edit : in case, static_cast<unsigned char>(*data++)
enough.
two's complement not guaranteed standard; in clause 3.9.1:
7 - [...] representations of integral types shall define values use of pure binary numeration system. [example: international standard permits 2's complement, 1's complement , signed magnitude representations integral types. — end example ]
so code assumes two's complement going have perform appropriate manipulations manually.
that said, conversion function unnecessary (and possibly incorrect); signed-to-unsigned conversions can use standard integral conversion (4.7):
2 - if destination type unsigned, resulting value least unsigned integer congruent source integer (modulo 2n n number of bits used represent unsigned type). [ note: in two's complement representation, conversion conceptual , there no change in bit pattern (if there no truncation). — end note ]
corrected code, using static_cast
::
constexpr uint32_t operator()( const char* data ) const { uint32_t crc = ~0; while (auto c = static_cast<unsigned char>(*data++)) crc = (crc >> 8) ^ m_[(crc & 0xff) ^ c]; return ~crc; }
Comments
Post a Comment