Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何编写constexpr交换函数来更改整数的尾数?_C++_C++14_Endianness_Constexpr_C++17 - Fatal编程技术网

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;
}