C++ 评估';如果';编译时的子句

C++ 评估';如果';编译时的子句,c++,optimization,c++17,if-constexpr,C++,Optimization,C++17,If Constexpr,考虑以下代码段: #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())

考虑以下代码段:

#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);
}
#包括
#包括
无效g(未签名){
// ...
}
模板
空f(UIntT n)
{
如果constexpr(std::numeric_limits::max()>std::numeric_limits::max())
{
如果(n>std::numeric_limits::max())
抛出std::length_错误(“太长”);
}
g(n);
}
我想知道“if constexpr”子句在这里是否真的有用。编译器是否足够聪明,能够找出给定UIntT的“if”子句是否为真?如果是,该标准是否强制要求这样做

编译器是否足够聪明,能够找出给定的
UIntT
if
子句是否为真

大多数是

如果是,该标准是否强制要求这样做

不,有些优化被命名为(RVO:s等),后来被纳入语言标准,但据我所知,
deac0de
优化没有标准化

... 但是
constexpr

< > > <强> >不可> <强>编译器将保留该块(如果条件是<代码> false >代码>),但您决定优化代码。

使用<代码>如果CONEXPRP与C++代码没有任何区别,如果根据C++标准。< /P> 然而,稍有不同的变体可能会导致编译单元使用的符号出现明显差异。在我看来,这可能会引起明显的差异

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


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

在这种情况下,大多数编译器会删除完整的
if
-块,除非
::max()>::max()
-至少在优化时是这样-但作为程序员,您希望确保在这种意义上是这样的,让它
constexpr
是有意义的。如果编译完成,您知道对于
::max()Check out更少的类型,它不会显示在汇编中code@doug这里可能仍然需要涉及非constexpr
n
的运行时检查,那么
static\u assert
有什么帮助呢?运行时检查不涉及n的值。只是它是一种类型。所以它工作正常,如果条件有效,就会被删除。@doug仍然不明白你的意思。请使用
static\u assert
编写相应的代码行。这比我的天真想法要好,所以你可以得到我的投票,但是“虽然他们可能会用constexpr消除它”听起来好像有选择?有吗?@tedl在调试版本中,当然有;死代码优化通常在调试中被跳过,它允许您将指令指针移动到死分支中。可以在优化之前消除
if constexpr
分支。因此,如果您的内存非常有限,并且不想优化调试版本,那么它可能会有用处。一个“应该”保留
constexpr
块的调试版本是否合法?我可以理解为什么人们会想要它,但我的解释是,按照标准是不可能发生的。@tedly在无法访问的程序集中发生的事情并不是标准所要解决的。难道标准不要求对
false
代码块进行赋值(作为正确的代码)并将其丢弃吗?