代码
cpp
///
/// @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 的版本
cpp
template <typename T>
requires(std::is_same_v<T, uint8_t>)
constexpr T Reverse(T value)
后续表格的建立基于这个版本。
翻转一个 8 位以上的整型的位,等价于逐个字节翻转,然后翻转字节序。这是可以用查表法优化的理论基础。
使用 constexpr 生成一个表格
cpp
// 运行时计算路径
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 的版本
cpp
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()
,为编译时计算和运行时计算分别定制了逻辑。
测试
cpp
// 0b10100111 = 0xa7 重复 8 次。
// 0xa7a7a7a7a7a7a7a7
constexpr uint64_t num = base::bit::Reverse(static_cast<uint64_t>(0b1010011110100111101001111010011110100111101001111010011110100111));
std::cout << base::ToHexString(num) << std::endl;
运行结果
bash
0xa84
0xe5e5e5e5e5e5e5e5

使用计算器验证