假设我有一个简单的函数可以做这样的事情:
template<typename T>
T get_half(T a){
return 0.5*a;
}
这个函数通常会用 T 为 double 或 float 来计算。 该标准规定 0.5 将是 double (0.5f 表示 float )。 如何编写上面的代码,使 0.5 始终为 T 类型,以便在计算产品或返回时不进行强制转换? 我想要的是 0.5 在编译时成为 T 类型的常量。这个问题的重点是我想避免在运行时进行转换。
例如,如果我写:
template<typename T>
T get_half(T a){
return T(0.5)*a;
}
我能绝对确定 T(0.5) 在编译时求值吗? 如果没有,实现这一目标的正确方法是什么?如果需要,我可以使用 c++11。
提前谢谢你。
在 c++11 中,我有一个 numeric_traits 类,如下所示(在头文件中)
template<typename Scalar>
struct numeric_traits{
static constexpr Scalar one_half = 0.5;
//Many other useful constants ....
};
所以在我的代码中,我会将其用作:
template<typename T>
T get_half(T a){
return numeric_traits<T>::one_half*a;
}
这就是我想要的,即 0.5 在编译时以我需要的精度解析,并且在运行时没有发生转换。但是缺点是:
- 每次需要新常量时我都需要修改 numeric_traits
- 语法可能太冗长烦人了? (当然,这真的不是什么大问题)
- 如果有类似这样的东西会很好:constant(0.5) 在运行时解析为 T 类型。
再次感谢您。
最佳答案
没有也不可能有任何方法强制常量在运行时永远不被计算,因为有些机器根本没有可以加载类型的所有可能值的单一指令。例如,机器可能只有一个 16 位加载常量指令,其中 0x12345678
需要在运行时计算为 0x1234 << 16 | 0x5678
。或者,可以从内存中加载这样一个常量,但这可能是比计算它成本更高的操作。
你需要稍微相信你的编译器。在可行的系统上,任何具有任何优化量的编译器都将以与翻译 T(0.5)
相同的方式翻译 0.5f
,假设 T
是 float
。 0.5f
将以最适合您的平台的方式计算。这可能涉及将其作为常量加载,或者可能涉及计算它。或者谁知道呢,您的编译器可能会将 T(0.5)*a
更改为 a/2
,如果结果相同的话。
在您的问题中,您举了一个添加 numeric_traits
帮助程序类的示例。 IMO,这太过分了。在 constexpr
产生影响的极不可能的情况下,您可以只写
template <typename T>
T get_half(T a) {
constexpr T half = 0.5;
return half * a;
}
但是,在我看来,这仍然弊大于利:您的 get_half
现在不能再用于非文字类型。它要求类型支持从常量表达式中的 double
转换。假设您有一个任意精度的 rational
类型,在编写时没有考虑到 constexpr
。现在您的 get_half
无法使用,因为初始化 constexpr T half = 0.5;
无效,即使 0.5 * a
可能已经编译。
即使您的 numeric_traits
辅助类也是如此;它不是因为我将它移动到函数体中而无效。
关于c++ - 如何在模板中定义浮点常量。避免在运行时强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28384981/