【问题标题】:Does undefined behavior affect static_assert?未定义的行为会影响 static_assert 吗?
【发布时间】:2019-03-06 19:52:49
【问题描述】:

考虑以下代码:

SomeType x=getX();
for(auto mask = 1u<<(CHAR_BIT*sizeof x - 1);/*...*/;/*...*/)
{
    static_assert(sizeof mask>=sizeof x, "Type of numeric parameter is too long");
    /*...*/
}

在这里,mask 将具有 unsigned 类型。假设SomeTypelong long。然后mask 的初始化将由于移位太多而产生未定义的行为。但是 OTOH,有一个 static_assert,它检查未定义的行为在运行时不会发生(因为代码将无法编译)。

但由于 UB 会导致时间悖论和其他意外,我不太确定 static_assert 在这种情况下是否能保证实际工作。有什么理由可以确定这一点吗?还是应该重做这段代码以使static_assert 出现在mask 初始化之前?

【问题讨论】:

  • 您可以使用auto mask = 1u; static_assert(...); mask &lt;&lt;= HAR_BIT*sizeof x-1; 完全避免该问题。
  • UB 很棘手。只需将断言移到计算上方以确保它具有正确的值,例如 SomeType x=getX(); static_assert(sizeof(x) &lt; whatever_value_you_need, "Type of numeric parameter is too long"); ...
  • @RSahu 我已将示例代码编辑得更简单,更接近我的实际用例。
  • @Ruslan,更新后的代码为在SomeType x = ...; 之后移动static_assert 提供了更强有力的理由。在循环中这样做有什么意义?
  • 我们可以用更多的括号看到这个吗?看到左移、乘法、sizeof 和减法没有任何一个,我有点不高兴。

标签: c++ undefined-behavior static-assert


【解决方案1】:

既然您知道您将使用unsigned 作为mask 的类型,则无需依赖mask 来执行static_assert。在循环开始之前立即执行。

SomeType x = getX();
static_assert(sizeof 1u >= sizeof x, "Type of numeric parameter is too long");

for(auto mask = 1u << CHAR_BIT*sizeof x-1; /*...*/; /*...*/)
{
    /*...*/
}

更简洁的选择是使用辅助函数。

template <typename RetType, typename SomeType>
RetType make_mask(RetType in, SomeType const& x)
{
   static_assert(sizeof in >= sizeof SomeType, "Type of numeric parameter is too long");
   return (in << (CHAR_BIT*sizeof SomeType)-1);
}

并使用

for(auto mask = make_mask(1u, x); /*...*/; /*...*/)
{
    /*...*/
}

【讨论】:

  • 这种方法的缺点是您重复了1u 并增加了维护成本(Ruslan 在 cmets 中提到过,但问题中没有)
  • @TimRandall,公平点。我更新了答案来解决这个问题。
【解决方案2】:

如果SomeType 是一个整数类型并且您使用的是 C++11 或更高版本,您可以使用以下方法完全消除断言:

auto one = std::make_unsigned<SomeType>::type(1);
for(auto mask = one << CHAR_BIT*sizeof x-1; /*...*/; /*...*/)
{
    /*...*/
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 2016-09-04
    相关资源
    最近更新 更多