将C++模板类型T修改为"long T"?

Bre*_*ust 11 c++ templates types

有没有办法加倍乘法返回的精度(以避免溢出)?

template<class T> class MyClass {
     T multiply (T a, T b) { return a * b; }
}
Run Code Online (Sandbox Code Playgroud)

就像是:

long T multiply (T a, T b) { return a * b; }
Run Code Online (Sandbox Code Playgroud)

因此,无论是'int','long'还是'double',都会从multipal返回'long int','long long'或'long double'.

这是一个普遍的问题.我正在通过内部使用double来解决它.但我的问题是,是否有任何机制可以将类型提升为C++中的"长"变体?

And*_*owl 14

一种可能的解决方案是定义您自己的类型特征:

template<typename T>
struct add_long { typedef T type; };

template<>
struct add_long<int> { typedef long int type; };

template<>
struct add_long<double> { typedef long double type; };

template<>
struct add_long<long int> { typedef long long int type; };

// And so on...
Run Code Online (Sandbox Code Playgroud)

这就是你在课堂上使用它的方法:

template<class T>
class MyClass {
public:
    typedef typename add_long<T>::type longT;
    longT multiply (longT a, longT b) { return a * b; }
};
Run Code Online (Sandbox Code Playgroud)

这是一个小测试:

#include <type_traits>

int main()
{
    MyClass<int> m;
    auto l = m.multiply(2, 3);
    static_assert(std::is_same<decltype(l), long int>::value, "Error!");
}
Run Code Online (Sandbox Code Playgroud)

  • 根据预期的用途,您可能希望从通用模板中省略`type`,或者如果您尝试使用没有`long'er版本的类型并因此会溢出,则确保您收到编译错误无论如何.为了安全起见,您可以使用`int8_t` - >`int16_t`,`int16_t` - >`int32_t`和`int32_t` - >`int64_t`来定义特殊化,以确保您确实在每个阶段增加大小.由于那些是可选类型,因此可移动性略低,但在系统上代码没有移植到"multiply"会溢出,这是最好的避免. (3认同)
  • @SteveJessop:"unsigned"部分被"等等"评论所涵盖;-) (2认同)
  • 你想要`a`和`b`仍然是T? (2认同)
  • @Rubistro然后如果`a`和`b`仍然是'T`,不要忘记在**乘之前将它们(或至少其中一个)转换为'longT`**,否则乘法将是upcast**溢出后的较大型**. (2认同)