【问题标题】:Does Boost or the Standard Library provide a way to check whether a cast is lossless?Boost 或标准库是否提供了一种检查强制转换是否无损的方法?
【发布时间】:2015-05-11 01:44:40
【问题描述】:

我正在寻找一个标准库或 Boost 函数,它可以将一个数字无损地转换为另一种原始类型,并以某种方式通知我该转换是否是无损的(如果不是,则抛出异常)。以下是一些示例:

auto x = lossless_cast<double>(1u); // ok, double can represent 1
auto x = lossless_cast<int>(1.2); // fail, int can't represent 1.2
auto x = lossless_cast<int>(1E200); // fail, int can't represent 1E200

boost::numeric_cast 很接近,因为它会拾取超出目标类型数值范围的强制转换,但如果它们是无损的,但目标类型中则不会(参见我的第二个示例)。

有一个SO question for the C language which provides some hand-rolled solutions to this problem,但我追求的是boost或标准库解决方案,基本上具有以下功能:

template <typename out, typename in>
out lossless_cast(in in_value)
{
  out out_value = static_cast<out>(in_value);

  if (static_cast<in>(out_value) != in_value)
    throw; // some exception

  return out_value;
}

这个功能存在吗?

【问题讨论】:

  • 编写一个函数来执行转换,然后比较之前和之后的相等性。
  • 如果您期待一个没有演员往返的解决方案,这可能是一个比您意识到的更难的问题。例如,float 不能代表 16,777,217。
  • @IgorTandetnik:这不是一个好主意 - 在某些情况下会产生 未定义的行为(例如问题中的 lossless_cast&lt;int&gt;(1E200); 案例)。
  • 有趣的是 double 也不能无损地表示 1.2.... ;)
  • 谁能结束这个问题,请再读一读我的问题。这不是那个问题的重复。

标签: c++ boost


【解决方案1】:

我很确定标准中没有预先推出任何内容,并且不知道 boost 中的任何内容,但它是一个大库。任何使用强制转换的实现都必须小心 未定义的行为,因为 4.9 [conv.fpint] 的超出范围的值,但正如 boost::numeric_cast&lt;&gt; 表面上处理的那样,您可以使用:

template <typename U, typename T>
inline U is_lossless(T t)
{
    U u = boost::numeric_cast<U>(t);
    T t2 = boost::numeric_cast<T>(u); // throw if now out-of-range
    if (t != t2)
        throw whatever-you-like;
    return u;
}

恢复t2 时对numeric_cast&lt;&gt; 的需求最不明显:它确保u 仍在范围内,因为从int64_t xdouble y 的值转换可能成功但被近似y 中的整数值超出了 int64_t 的范围,因此从 double 回滚具有未定义的行为。

上述的合法性/稳健性要求boost::numeric_cast&lt;&gt; 正确避免未定义的行为,我尚未验证。

【讨论】:

  • 我很确定 boost::numeric_cast 的意图是避免 UB 案例。它在当前的实施中是否真的成功很难说;见stackoverflow.com/q/25857843
  • @Nemo:您希望这是他们的意图,尽管这可能很难快速完成(就 CPU 周期而言),而且他们可能在特定的 CPU 上发现了未定义的行为来提升targetted 的可移植性要求是可以接受的,而不是标准规定的跨所有可能目标的可移植性。我刚刚在我的电脑上提取了代码,并会查看您的链接 - 干杯。
  • 既然T的类型可以从参数中推断出来,那么将typename U设为first模板参数是否有价值?我认为,这将允许类似于 boost 和核心语言提供的“转换”语法。
  • @DrewDormann:当然 - 让我自己扭曲了。干杯。
猜你喜欢
  • 1970-01-01
  • 2013-11-02
  • 2022-06-29
  • 2020-01-20
  • 1970-01-01
  • 2016-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多