代码
////// @brief 左右翻转位。////// @note 翻转后,最低位位将变为最高位,最高位将变为最低位。//////template <typename T>requires(std::is_same_v<T, uint8_t>)constexpr T Reverse(T value){int32_t bit_count = sizeof(T) * 8;for (int32_t i = 0; i < bit_count / 2; i++){int32_t left_index = bit_count - 1 - i;int32_t right_index = i;bool left_bit = base::bit::ReadBit(value, left_index);bool right_bit = base::bit::ReadBit(value, right_index);base::bit::WriteBit(value, left_index, right_bit);base::bit::WriteBit(value, right_index, left_bit);}return value;}////// @brief 左右翻转位。////// @note 翻转后,最低位位将变为最高位,最高位将变为最低位。//////template <typename T>requires(std::is_integral_v<T> && !std::is_same_v<T, uint8_t>)constexpr T Reverse(T value){if (std::is_constant_evaluated()){// 编译时计算路径int32_t bit_count = sizeof(T) * 8;for (int32_t i = 0; i < bit_count / 2; i++){int32_t left_index = bit_count - 1 - i;int32_t right_index = i;bool left_bit = base::bit::ReadBit(value, left_index);bool right_bit = base::bit::ReadBit(value, right_index);base::bit::WriteBit(value, left_index, right_bit);base::bit::WriteBit(value, right_index, left_bit);}return value;}// 运行时计算路径class Table{private:std::array<uint8_t, 256> _table{};public:constexpr Table(){for (int32_t i = 0; i < 256; i++){_table[i] = base::bit::Reverse(static_cast<uint8_t>(i));}}constexpr uint8_t operator[](uint8_t index) const{return _table[index];}};constexpr Table table{};uint8_t *bytes = reinterpret_cast<uint8_t *>(&value);for (size_t i = 0; i < sizeof(T); i++){bytes[i] = table[bytes[i]];}std::reverse(bytes, bytes + sizeof(T));return value;}
先准备一个针对 uint8_t 的版本
template <typename T>requires(std::is_same_v<T, uint8_t>)constexpr T Reverse(T value)
后续表格的建立基于这个版本。
翻转一个 8 位以上的整型的位,等价于逐个字节翻转,然后翻转字节序。这是可以用查表法优化的理论基础。
使用 constexpr 生成一个表格
// 运行时计算路径class Table{private:std::array<uint8_t, 256> _table{};public:constexpr Table(){for (int32_t i = 0; i < 256; i++){_table[i] = base::bit::Reverse(static_cast<uint8_t>(i));}}constexpr uint8_t operator[](uint8_t index) const{return _table[index];}};constexpr Table table{};
翻转一个字节只需查表即可完成。对于 64 位整型,需要查表 8 次,然后翻转 8 个字节。
针对非 uint8_t 的版本
template <typename T>requires(std::is_integral_v<T> && !std::is_same_v<T, uint8_t>)constexpr T Reverse(T value)
中使用了 std::is_constant_evaluated()
,为编译时计算和运行时计算分别定制了逻辑。
测试
// 0b10100111 = 0xa7 重复 8 次。// 0xa7a7a7a7a7a7a7a7constexpr uint64_t num = base::bit::Reverse(static_cast<uint64_t>(0b1010011110100111101001111010011110100111101001111010011110100111));std::cout << base::ToHexString(num) << std::endl;
运行结果
0xa84
0xe5e5e5e5e5e5e5e5
使用计算器验证