将C++整数类型模板参数转换为"更长"的整数类型

Kev*_*son 1 c++ templates types

我有一个模板化函数,它接受一个整数类型并对两个输入参数执行数学运算:

template<typename T, typename R>
R multiply( const T& lhs, const T& rhs ) {
  R ans = static_cast<R>( lhs ) * static_cast<R>( rhs );
  return ans;
}
Run Code Online (Sandbox Code Playgroud)

(为简单起见,假设类型T和R始终是无符号整数类型,或者我执行合适的检查以确保.)

在这个人为的例子中,你可以看到我正在做一个简单的乘法(仅用于说明).我们的想法是传递一个类型为R的类型R,其类型为T的两倍.这将允许完整的产品适合返回值:

uint64_t Product64 = multiply<uint32_t,uint64_t>( 0xFFFFFFFF, 0xFFFFFFFF );
uint16_t Product16 = multiply<uint8_t,uint16_t>( 0xFF, 0xFF );
Run Code Online (Sandbox Code Playgroud)

我想知道是否有任何方法可以省去第二个模板参数,并在编译时自动计算[类型T] [至少]两倍多位宽的类型.

注意:只使用R的最大可用积分类型(uint64_t)对我来说不是解决方案.理想情况下,我想要一个编译时计算类型,其大小足以容纳两倍于T的类型(例如,当T = uint8_t,R = uint16_t时).

在我看来,应该可以使用limit或type_traits或类似的东西,但到目前为止我还没有想到解决方案.C++ 11或更高版本没问题.我宁愿避免提升,但如果这是唯一的方法,我也有兴趣看到基于提升的解决方案.

Rus*_*lan 5

您可以创建自己的模板大小类型,并使用它们来定义返回类型,如下所示:

#include <cstdint>
template<int N>
struct sized_uint {};
template<> struct sized_uint<8 > { using type=std::uint8_t; };
template<> struct sized_uint<16> { using type=std::uint16_t; };
template<> struct sized_uint<32> { using type=std::uint32_t; };
template<> struct sized_uint<64> { using type=std::uint64_t; };

#include <climits>
template<typename T>
auto multiply(T lhs, T rhs)
{
  using R=typename sized_uint<CHAR_BIT*sizeof(T)*2>::type;
  return static_cast<R>(static_cast<R>(lhs) * static_cast<R>(rhs));
}
Run Code Online (Sandbox Code Playgroud)

现场观看.