【发布时间】:2018-07-26 09:18:42
【问题描述】:
我目前正在编写一个模板化的 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;
}
我不太关心这两个版本的可读性。我也不关心这样一个事实,在这里使用整数类型可能是没用的。我只想知道:
- 这些实现之间有区别吗?
- 如果是,是什么?
- 另外,此代码编译器上可能的优化是否取决于?
编辑:
- 如果我想支持自定义数字类型,是否会进行任何更改?
编辑:
正如 cmets 中所指出的,上面使用的链式比较实际上是错误的。代码应该是这样的:
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;
}
【问题讨论】:
-
哎呀,链式比较。 99.99% 的时间都是错误的。
-
您可以声明一些具有适当类型的有意义的常量,而不是使用幻数,并在每次需要该值时使用它们而不是强制转换。
-
“在我的所有情况下,这当然被解释为
static_cast。” ——你没有考虑的情况呢?当T是一个强类型枚举,或者可能是一个指针,因为有人不小心传入了错误的参数,那又会怎样呢?你想默默地接受这一点,还是想让你的编译器告诉你你做错了什么? -
嗯,除了在 cmets 中已经指出的内容之外,我还编写了两个 (
constexpr) 版本,一个带有semi_major_axes,一个没有那个比较,而不是一个带有默认值的函数参数。
标签: c++ templates type-conversion static-cast