`if constexpr` vs`if`根据编译器优化和代码性能

Ant*_*hov 2 c++ c++17 if-constexpr

考虑一个func非常重要的功能模板.它可以用T=Type1其他类型实例化.部分功能逻辑依赖于T它的实例化.

可以明确地使用if constexpr(代码B)或使用香草if代替(代码A),而编译器可能优化代码.

但是,我想知道,没有constexpr(代码A)的实现有何不同?编译器是否能够if在实例化时检测(在代码A中)哪个分支在编译时使用?它仍然(换码)生成代码效率不高?

代码A. 没有 if constexpr:

template<class T>
void func(T argument)
{
    // some general type-independent logic
    if (std::is_same<Type1,T>::value)
    {
        // do something
    }
    else
    {
        // do something else
    }
    // some general type-independent logic
}
Run Code Online (Sandbox Code Playgroud)

代码B. if constexpr:

template<class T>
void func(T argument)
{
    // some general type-independent logic
    if constexpr (std::is_same<Type1,T>::value)
    {
        // do something
    }
    else
    {
        // do something else
    }
    // some general type-independent logic
}
Run Code Online (Sandbox Code Playgroud)

代码A和B都编译,do something并且do something else适用于任何代码T.

有一些类似的问题:

如果代码B由于某种原因(当两个分支都是格式良好的时候)优于代码A时,上述问题不会回答.

我看到的唯一优势是明确告诉程序员这if是编译时; 但是,我会说条件表达式是不言自明的.

Bar*_*rry 9

if constexpr不是为了优化.编译器非常擅长优化分支if (true)或者if (false)(因为我们正在谈论常量表达式,这就是它归结为).这是OP中示例的一个Godbolt演示 - 你会注意到gcc和clang,即使在-O0,也不会为一个简单的发出分支if.

if constexpr是所有关于确保只有一个分支if实例化.这对于编写模板非常重要和有价值 - 因为现在我们实际上可以在同一函数体内编写有条件的编译代码而不是编写多个人工函数来避免实例化.

也就是说,如果你的条件是一个已知的常量表达式 - 只需要总是使用if constexpr,无论你是否需要实例化的好处.这样的决定没有任何缺点.这使得读者更清楚这种情况确实是不变的(因为否则它甚至不会编译).它还会强制将表达式的评估作为一个常量(一个轻微的变体导致gcc发出一个分支-O0,而不是在-O1那里),is_constant_evaluated()从长远来看,随着即将到来的增加可能变得更加重要(甚至可能否定我的开头段落) ).


我看到的唯一优势是明确告诉程序员这是否是编译时; 但是,我会说条件表达式是不言自明的.

具体来说,是的,std::is_same<X, Y>::value是"不言自明",它是一个不变的表达......因为我们碰巧熟悉std::is_same.但是,不管foo<X>::value是一个常数表达式还是foo<X>() + bar<Y>()一个常量表达式或任何比这更复杂的事情,它都不太明显.

它看来if constexpr这使得它的编译时不言自明,而不是条件本身的内容.

  • 如果constexpr在"不需要"时的最大优点是你得到一个*错误*如果你错了它就是错误的. (3认同)