C++ 如何编写constexpr交换函数来更改整数的尾数?
如何编写一个C++ 如何编写constexpr交换函数来更改整数的尾数?,c++,c++14,endianness,constexpr,c++17,C++,C++14,Endianness,Constexpr,C++17,如何编写一个constepr函数来交换整数的尾数,而不依赖于编译器扩展,你能举个例子说明如何做到吗?是的,这很简单;下面是一个递归(与C++11兼容)实现(仅限无符号整数类型): 这种形式的优点是,因为它不使用循环或递归,所以几乎可以保证获得最佳的程序集输出—在x86-64上,clang甚至可以做到这一点。受ecatmur的启发,我建议以下解决方案,当编译器未检测到bswap时(O(log(n))vs O(n))。假设N通常是(digits()-step))“整数的端点数”是多少?15的endi
constepr
函数来交换整数的尾数,而不依赖于编译器扩展,你能举个例子说明如何做到吗?是的,这很简单;下面是一个递归(与C++11兼容)实现(仅限无符号整数类型):
这种形式的优点是,因为它不使用循环或递归,所以几乎可以保证获得最佳的程序集输出—在x86-64上,clang甚至可以做到这一点。受ecatmur的启发,我建议以下解决方案,当编译器未检测到bswap时(O(log(n))vs O(n))。假设N通常是(digits()-step))“整数的端点数”是多少?15的endianness是什么?@KerrekSB:在C++环境中(以及大多数编程),当一个人说integer时,他们通常指的是integer对象。也就是说,内存中用于存储整数数据的区域,通常是基本整数类型之一(char、short、int、long和long,以及它们的无符号变体)。你真的从来没有见过这种用法吗?@BenjaminLindley:当然。“我只是觉得这个问题太不明确了。”本贾明林德利说,“我们可以猜,但这个问题的措辞很糟糕,因为整数没有端点。(这正是Kerrek SB试图指出的)。这一点值得一提,因为(从这里的问题判断)许多人不会混淆值和表示之间的区别,也不会编写脆弱或错误的代码result@M.M.嗯,我不同意,我认为措辞很好。我理解Kerrek的观点,但我认为这是不必要的迂腐和愚蠢。我不能马上想出一个更好的措辞来回答这个问题,也不会浪费我的时间去想一个更好的措辞,因为每个知道endianness是什么的人都理解它,甚至Kerrek也是如此。这个解决方案的时间复杂度实际上也是Θ(N),因为内部循环(不包括优化)具有Θ(N/logn)的摊销复杂度(外循环的每次迭代)。为了得到实际的Θ(log N),需要对位掩码进行记忆,例如预计算到数组中。@ArneVogel这是真的,我只是假设位掩码将是编译时常量,因为生成它们的函数是constexpr。您可能有兴趣知道这个答案是由cppreference的fold表达式docs链接到的(不确定是你自己放的还是别人放的)。不是我,但谢谢你指出-很高兴有一个不只是求和的例子。是的,我非常感谢:)因为CPP参考文件而来这里,我也非常感谢!
#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);
}
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)>{});
}
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<digits<T>();i+=2*step){
mask|=(~T(0)>>(digits<T>()-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=digits<unsigned char>();i<digits<T>();i*=2){
n = ((n&(~(alternating_bitmask<T>(i))))>>i)|
((n&( (alternating_bitmask<T>(i))))<<i);
}
return n;
}