如何检查强制转换是否会导致目标类型上溢或下溢?

qua*_*ant 2 c++ boost

标准库/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。

Sea*_*ine 6

不幸的是,C++ 标准库中不存在这样的函数。这留下了一些选择:


选项1: boost::numeric_cast

如果您可以访问 Boost,那么boost::numeric_cast应该完全按照您的意愿行事。它将在两种数字类型之间执行转换,除非转换超出目标类型的范围。在这种情况下,boost::numeric::bad_numeric_cast会抛出异常。


选项#2: gsl::narrow()

或者,gsl::narrow是一个不错的选择。如果您同意将GSL带入您的项目,我认为它比 Boost 更可取。


选项#3:自己动手。

如果您对实现自己的转换感到好奇,可以查看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 的那么远,但可以想象,可以修改以满足您的需求。

  • 任何人都会遇到这个问题:条件还不够,因为 `static_cast&lt;unsigned&gt;(static_cast&lt;int&gt;(X))` 不会修改该值。当源和目标符号不同时,还需要显式检查符号不匹配。 (4认同)