如何编写constexpr交换函数来更改整数的尾数
How to write constexpr swap function to change endianess of an integer?
如何在不依赖编译器扩展的情况下编写constexpr
函数来交换整数的尾数,您能举一个如何做到这一点的例子吗?
是的,这很容易;这里有一个递归(兼容C++11)实现(仅限无符号积分类型):
#include <climits>
#include <cstdint>
#include <type_traits>
template<class T>
constexpr typename std::enable_if<std::is_unsigned<T>::value, T>::type
bswap(T i, T j = 0u, std::size_t n = 0u) {
return n == sizeof(T) ? j :
bswap<T>(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1);
}
示例。
这里我使用j
作为累加器,n
作为循环计数器(索引字节)。
如果你有一个支持C++17折叠表达式的编译器,那么就有可能写出一些可以扩展为你手工编写的东西:
template<class T, std::size_t... N>
constexpr T bswap_impl(T i, std::index_sequence<N...>) {
return ((((i >> (N * CHAR_BIT)) & (T)(unsigned char)(-1)) <<
((sizeof(T) - 1 - N) * CHAR_BIT)) | ...);
}; // ^~~~~ fold expression
template<class T, class U = typename std::make_unsigned<T>::type>
constexpr U bswap(T i) {
return bswap_impl<U>(i, std::make_index_sequence<sizeof(T)>{});
}
这种形式的优点是,因为它不使用循环或递归,所以几乎可以保证获得最佳的汇编输出——在x86-64上,clang甚至可以使用bswap
指令。
受ecatmur的启发,我提出了以下解决方案,当编译器未检测到bswap时,该解决方案可能具有更好的性能(O(log(n))vs O(n))。假定N通常<8这可能无关紧要,仍然:
using std::numeric_limits;
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value,T>::type
constexpr alternating_bitmask(const size_t step){
T mask(0);
for (size_t i=0;i<numeric_limits<T>::digits;i+=2*step){
mask|=(~T(0)>>(numeric_limits<T>::digits-step))<<i;
}
return mask;
}
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value,T>::type
constexpr bswap(T n){
for (size_t i=numeric_limits<unsigned char>::digits;
i<numeric_limits<T>::digits;
i*=2) {
n = ((n&(~(alternating_bitmask<T>(i))))>>i)|
((n&( (alternating_bitmask<T>(i))))<<i);
}
return n;
}
由于这种形式比ecatmur的解决方案更复杂,编译器的优化工作更困难,但clang仍然发现我们指的是bswap。
最后,C++23允许使用标准库中的新函数std::byteswap轻松实现这一点:https://en.cppreference.com/w/cpp/numeric/byteswap
相关文章:
- 如何将字符串和整数读取到两个单独的动态数组中的程序编写?
- 编写一个读取五个整数并执行一些任务的C++程序
- 我需要编写一个程序来读取一个文件,该文件将输出所有唯一的整数,如果已经看到整数,它将被关闭
- 编写一个程序,提示用户输入一个整数,然后输出数字的单个数字和数字的总和
- 给定一个整数 N>0,区间 [0, 2^N) 中有多少个整数正好有 N-1 个设置位?编写一个返回正确答案的简短函数
- 编写一个程序,输入整数 n 并打印该数字的字符数(符号除外)
- 编写所需的代码以创建动态一维整数数组
- 如何编写模板函数来添加整数但连接字符串和字符类型?
- 如何编写模板以转换为基于整数/枚举的模板化类型
- (显示金字塔)编写一个程序,该程序提示用户输入1到15的整数并显示金字塔
- 编写一个功能,该函数将使用框架交换两个整数
- 编写 LLVM 整数/字符串输入
- 字符 * 和字符串在C++中有何不同?(在描述中编写代码)
- 如何编写一个 boost::spirit::qi 解析器来解析从 0 到 std::numeric_limits:<int>:max() 的整数范围?
- 一个整数可以安全阅读,而另一个线程可能会在其中编写
- 编写一个程序,该程序在0-99范围内生成10000个随机整数,并从随机数据中产生直方图
- C++11 编写模板以选择更大的整数类型的方法
- 如何编写constexpr交换函数来更改整数的尾数
- 编写一个atoi以将字符串转换为整数
- 编写一个递归函数来乘以2个整数