代码之家  ›  专栏  ›  技术社区  ›  Ruslan PiotrNycz

未定义的行为会影响静态断言吗?

  •  0
  • Ruslan PiotrNycz  · 技术社区  · 6 年前

    考虑下面的代码:

    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 认为 SomeType long long .然后初始化 面具 由于移动过多,将有未定义的行为。但是奥托,有一个 static_assert ,它检查未定义的行为不能在运行时发生(因为代码将无法编译)。

    但由于UB会导致时间悖论和其他意外,我不太确定这一点 静态断言 在这种情况下,保证能真正起作用。有什么理由确定这一点吗?还是应该重新编写此代码以使 静态断言 在初始化之前出现 面具 ?

    0 回复  |  直到 6 年前
        1
  •  2
  •   R Sahu    6 年前

    既然你知道你要用 unsigned 作为 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; /*...*/; /*...*/)
    {
        /*...*/
    }
    

    一个更简洁的选择是使用helper函数。

    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); /*...*/; /*...*/)
    {
        /*...*/
    }
    
        2
  •  1
  •   Kit.    6 年前

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

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