标准库/Boost 中是否有一个函数可以检查强制转换是否会导致目标类型的上溢/下溢?例如:
unsigned value = static_cast<unsigned>(12.3); // this should pass (lossy but no overflow)
unsigned value = static_cast<unsigned>(1E123); // this should fail
unsigned value = static_cast<unsigned>(-2); // this should also fail
Run Code Online (Sandbox Code Playgroud)
这样的东西存在吗?对于上述示例,该功能可能具有与此类似的功能:
template <typename Source, typename Target>
bool checkNoOverflow(const Source value)
{
return value >= std::numeric_limits<Target>::lowest() && value <= std::numeric_limits<Target>::max();
}
Run Code Online (Sandbox Code Playgroud)
上面只是一个简化的例子,在这样的极端情况下会失败:
unsigned value = static_cast<unsigned>(-0.1); // valid, result is 0
Run Code Online (Sandbox Code Playgroud)
需要明确的是,我不是在问如何编写一个适用于所有情况的函数,而是我在寻找标准库中的现有功能或为我做这件事的 boost。
不幸的是,C++ 标准库中不存在这样的函数。这留下了一些选择:
boost::numeric_cast如果您可以访问 Boost,那么boost::numeric_cast应该完全按照您的意愿行事。它将在两种数字类型之间执行转换,除非转换超出目标类型的范围。在这种情况下,boost::numeric::bad_numeric_cast会抛出异常。
gsl::narrow()或者,gsl::narrow是一个不错的选择。如果您同意将GSL带入您的项目,我认为它比 Boost 更可取。
如果您对实现自己的转换感到好奇,可以查看Bjarne Stroustrup 的The C++ Programming Language 4th Edition ( ISBN 978-0321563842 )。
在第 11.5 章中,他将 a 定义narrow_cast为:
template<class Target, class Source>
Target narrow_cast(Source v)
{
auto r = static_cast<Target>(v); // convert the value to the target type
if (static_cast<Source>(r)!=v)
throw runtime_error("narrow_cast<>() failed");
return r;
}
Run Code Online (Sandbox Code Playgroud)
这个实现是非常简单的,没有 Boost 的那么远,但可以想象,可以修改以满足您的需求。