我目前正在编写模板化的c ++物理库。在我的函数中,我经常必须显式比较或设置某些数值。我的目标是编写尽可能通用的库,因此我想尽可能支持浮点数和整数类型。
为了获得正确的类型,我经常在代码中使用显式强制转换为T
。在我所有情况下,这当然都解释为static_cast
。因此,我的问题是:我是否真的需要static_cast
这些值?还是可以通过执行/不执行来获取运行时开销?
一个例子:
我目前有这样的功能:
template <class T> auto is_elliptic(T eccentricity, T semi_major_axes = T(1)) {
return T(0) <= eccentricity < T(1) && T(0) < semi_major_axes;
}
但是,我也可以这样写:
template <class T> auto is_elliptic(T eccentricity, T semi_major_axes = T(1.0)) {
return T(0.0) <= eccentricity < T(1.0) && T(0.0) < semi_major_axes;
}
像这样:
template <class T> auto is_elliptic(T eccentricity, T semi_major_axes = 1) {
return 0 <= eccentricity < 1 && 0 < semi_major_axes;
}
或像这样:
template <class T> auto is_elliptic(T eccentricity, T semi_major_axes = 1.0) {
return 0.0 <= eccentricity < 1.0 && 0.0 < semi_major_axes;
}
我对这两个版本的可读性都不在乎。我也不关心这个事实,在这里使用整数类型可能没有用。我想知道的是:
这些实现之间有区别吗?
如果是,那是什么?
另外,此代码编译器的可能优化是否依赖于?
编辑:
如果我想支持自定义数字类型,是否会有任何更改?
编辑:
正如评论中指出的那样,上面使用的链接比较实际上是错误的。该代码应类似于:
return T(0) <= eccentricity && eccentricity < T(1) && T(0) < semi_major_axes;
此外,可以使用
constexpr
版本对代码进行运行时优化:template <class T> constexpr auto is_elliptic(T eccentricity) {
return T(0) <= eccentricity && eccentricity < T(1);
}
template <class T> constexpr auto is_elliptic(T eccentricity, T semi_major_axes) {
return T(0) <= eccentricity && eccentricity < T(1) && T(0) < semi_major_axes;
}
最佳答案
取决于您想要什么。
此答案假定T
是int
或float
(尽管它适用于double
,long
或具有类似行为的自定义类型),并且x
具有类型T
。
如果使用强制转换:
这很容易理解。但是,对于在T
类型中不能表示常量的情况,请当心。 0.5>x
与(int)0.5>x
不同。
如果不使用演员表:
如果升级的操作数具有不同的类型,则会应用另外的一组隐式转换,这些转换被称为通常的算术转换,目的是产生通用类型。[...]
(来自https://en.cppreference.com/w/cpp/language/operator_arithmetic)
| T | Comparison | Equivalent to |
+-------+------------+---------------+
| int | 0<x | 0<x |
| int | 0.f<x | 0.f<(float)x | (*)
| float | 0<x | (float)0<x |
| float | 0.f<x | 0.f<x |
对于
(*)
,比较是在float
上完成的,而强制转换常量(int(0.f<x)
)将在整数上进行比较。对于其他情况,则相同。关于编译器开销:编译可能会稍微慢一些,但是考虑到标准库头的编译速度已经很慢了,所以这无关紧要。
关于c++ - 我是否需要static_cast我的数字模板值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51535286/