依靠任何数字类型(无符号、整数等)的隐式提升来加倍是否安全
Is it safe to rely on implicit promotion from any numeric type (unsigned, int, ...) to double?
我有一个用于图形的模板类,它采用权重类型的参数(可以是无符号的、整数的或双精度的)。此外,为了比较双精度,我使用以下类型的内联函数:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
inline bool EpsEqual(double x, double y, double epsilon = 1.e-10)
{
return !EpsLess(x,y) && !EpsLess(y,x);
}
以下类骨架中的比较器安全吗?
template <typename Weight>
class Graph
{
struct Edge
{
std::string from;
std::string to;
Weight weight;
};
struct LargestWeight
{
bool operator() (const Edge& e1, const Edge& e2) const
{
if (EpsEqual(e1.weight == e2.weight))
if (e1.from == e2.from)
return e1.to < e2.to;
else
return e1.from < e2.from;
return EpsLess(e2.weight, e1.weight);
}
};
// .. other stuff
};
当权重类型为无符号或 int 时,我会遇到不可预见的后果吗?还是有更好的方法来实现双重比较?
这正是模板的用途。
我建议您在仅使用 <
和 ==
运算符的模板类中实现 EpsLess
()。像这样:
template<typename Type> Compare {
public:
template<typename Ignore>
inline bool EpsLess(Type x, Type y, Ignore epsilon = Ignore())
{
return x < y;
}
};
然后专门用于双倍:
template<> Compare<double> {
public:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
};
您将像这样调用它:
if (Compare<Weight>::EpsEqual(e1.weight, e2.weight))
这将避免一堆无用的工作,用于非双重情况,并被移交给一个普通的<
操作员。
然后,您的家庭作业是按照新EpsLess
()将EpsEqual
()重新实现为模板函数本身。
不,您不能在所有情况下都信任整数的双重转换。
从整数到双精度的转换并不总是在不损失精度的情况下完成。因此,如果权重是可以保存大值的整数类型,例如size_t
所有 32 位整数都可以毫无问题地转换(也称为精度损失)。
相关文章:
- 通过网络、跨平台传递std::变体是否安全
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 在函数结束后使用指向变量的指针是否安全?
- 逐字节删除 void* 是否安全?
- 在 RAII 构造中修改 RVO 值是否安全?
- 线程调用的函数对对象删除是否安全?
- 将对象的字节复制到数组并再次复制回来是否安全
- std::memmove在同一对象之间是否始终安全
- 使用枚举为数组编制索引是否安全?
- 返回从字符串文本创建的静态string_view是否安全?
- 在cstlib中将#include_next替换为#include是否安全
- 由并发无序映射查找线程调用的函数是否安全?
- 使用 c++ 原子时编写"y=++x"是否安全?
- 从另一个线程发出信号是否安全?
- 从其存储的回调中删除 std::函数是否安全
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 当我在C++中调用 struce 的只读静态成员时,线程是否安全
- 同时调用 ASIO 对象的 API 是否安全?