简体   繁体   English

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

[英]`if constexpr` vs `if` in light of compiler optimization and code performance

Consider a function template func that is very performance critical. 考虑一个非常重要的功能模板func It can be instantiated with T=Type1 or some other type. 它可以用T=Type1或其他类型实例化。 Part of the function logic depends on T it is instantiated with. 部分功能逻辑依赖于T实例化。

One can either explicitly use a if constexpr (Code B) or use a vanilla if instead (Code A), while compiler probably optimizes the code. 一个可以显式使用if constexpr (代码B)或使用香草if代替(代码A),而编译器可能优化代码。

However, I wonder, how the implementation without constexpr (Code A) is any different? 但是,我想知道,没有constexpr (代码A)的实现有何不同? Isn't the compiler capable of detecting which branch of if (in Code A) to use at compile time while instantiating? 编译器是否能够在实例化时检测if (在代码A中)哪个分支在编译时使用? Can it still (for Code A) generate a less efficient code? 它仍然(换码)生成代码效率不高?

Code A. Without if constexpr : 代码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
}

Code B. With if constexpr : 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
}

Both codes A & B compile, as do something and do something else are well-formed for any T . 这两个代码A&B编译,如do somethingdo something else都能很好地形成任何T

There are some similar-sounding questions: 有一些类似的问题:

The aforementioned questions do not answer if Code B is preferable to Code A for some reason (when both branches are well-formed anyway). 如果代码B由于某种原因(当两个分支都是格式良好的时候)优于代码A时,上述问题不会回答。

The only advantage I see would be to tell the programmer explicitly that this if is compile-time; 我看到的唯一优势是明确告诉程序员这if是编译时; however, I would say the conditional expression is self-explanatory. 但是,我会说条件表达式是不言自明的。

if constexpr is not intended about optimization. if constexpr不打算进行优化。 Compilers are very good at optimizing away a branch that is if (true) or if (false) (since we're talking about constant expressions, that is what it boils down to). 编译器非常擅长优化if (true)if (false)的分支(因为我们正在讨论常量表达式,这就是它归结为)。 Here is a godbolt demo of the example in OP - you'll note that both gcc and clang, even on -O0 , do not emit a branch for a simple if . 这是OP中示例的一个Godbolt演示 - 你会注意到gcc和clang,即使在-O0 ,也不会为简单的if发出分支。

if constexpr is all about ensuring that only one branch of the if is instantiated . if constexpr是为了确保只实例化 if一个分支。 This is hugely important and valuable for writing templates - because now we can actually write conditionally compiling code within the body of the same function instead of writing multiple artificial functions just to avoid instantiation. 这对于编写模板非常重要和有价值 - 因为现在我们实际上可以在同一函数体内编写有条件的编译代码而不是编写多个人工函数来避免实例化。

That said, if you have a condition that is a known constant expression - just always use if constexpr , whether or not you need the instantiation benefit. 也就是说,如果你的条件是一个已知的常量表达式 - 只要总是使用if constexpr ,无论你是否需要实例化的好处。 There is no downside to such a decision. 这样的决定没有任何缺点。 It makes it clearer to readers that indeed this condition is constant (since otherwise it wouldn't even compile). 这使得读者更清楚这种情况确实是不变的(因为否则它甚至不会编译)。 It will also force the evaluation of the expression as a constant (a slight variant leads gcc to emit a branch at -O0 , thought not at -O1 ), which with the coming addition of is_constant_evaluated() may become more important in the long run (possibly even negating my opening paragraph). 这也将迫使表达的评价作为常数( 轻微变异导致的gcc发出分支在-O0 ,以为不-O1 ),它与即将加入is_constant_evaluated()有可能成为从长远来看更重要(甚至可能否定我的开头段落)。


The only advantage I see would be to tell the programmer explicitly that this if is compile-time; 我看到的唯一优势是明确告诉程序员这是否是编译时; however, I would say the conditional expression is self-explanatory. 但是,我会说条件表达式是不言自明的。

To address this specifically, yes, std::is_same<X, Y>::value is "self-explanatory" that it is a constant expression... because we happen to be familiar with std::is_same . 为了具体解决这个问题,是的, std::is_same<X, Y>::value是“不言自明”的,它是一个常量表达式...因为我们碰巧熟悉std::is_same But it's less obvious whether foo<X>::value is a constant expression or whether foo<X>() + bar<Y>() is a constant expression or anything more arbitrarily complicated than that. 但是foo<X>::value是一个常量表达式还是foo<X>() + bar<Y>()是一个常量表达式还是比这更复杂的任何东西都不太明显。

It's seeing if constexpr that makes the fact that it's compile-time self-explanatory, not the content of the condition itself. 它看if constexpr使得它的编译时不言自明,而不是条件本身的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM