4

考虑以下代码片段:

#include <limits>
#include <stdexcept>

void g(unsigned) {
    // ...
}

template<typename UIntT>
void f(UIntT n)
{
    if constexpr (std::numeric_limits<UIntT>::max() > std::numeric_limits<unsigned>::max())
    {
        if (n > std::numeric_limits<unsigned>::max())
            throw std::length_error("Too long.");
    }

    g(n);
}

我想知道“if constexpr”子句在这里是否真的有用。编译器是否不够聪明,无法确定给定 UIntT 的“if”子句是否为真?如果是这样,这是标准规定的吗?

4

2 回答 2

4

编译器是否不够聪明,无法确定该if子句对于给定的是否为真UIntT

大多数是。

如果是这样,这是标准规定的吗?

不,一些优化已经被命名(RVO:s 等),后来被纳入语言标准,但DEADC0DE优化不是标准化的(据我所知)。

...但是constexpr

符合标准的编译器无法在生成的二进制文件中保留该块(如果条件为false) - 但是您决定优化您的代码。

于 2019-09-27T18:22:43.537 回答
1

根据 C++ 标准,这种使用if constexpr与 an 没有明显区别。if

但是,稍微不同的变体可能会导致编译单元使用的符号存在明显差异。对我来说,这似乎是合理的,这会导致可观察到的差异。

大多数现代编译器可以并且将if (false)在优化期间减少它,即使不是constexpr,并且死分支消除是一个非常简单的优化。在调试版本中,他们可能会不理会死代码,而可能会使用constexpr.

编译器资源管理器非常适合回答此类问题的特定情况,因为它可以很容易地查看每个主要编译器生成的程序集。因此,如果您想知道默认 MSVC 2015 调试或发布设置是否存在差异,您可以在此处查看。

于 2019-09-27T21:44:08.837 回答