Two's complement is not guaranteed by the standard; in clause 3.9.1:
7 - [...] The representations of integral types shall define values by use of a pure binary numeration system. [Example: this International Standard permits 2's complement, 1's complement and signed magnitude representations for integral types. — end example ]
So any code that assumes two's complement is going to have to perform the appropriate manipulations manually.
That said, your conversion function is unnecessary (and possibly incorrect); for signed-to-unsigned conversions you can just use the standard integral conversion (4.7):
2 - If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two's complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is 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;
}