编译器是否被迫根据模板参数来评估if表达式?

问题描述 投票:1回答:1

考虑这个代码片段。

#include <iostream>

struct A {

    void f() { std::cout << "f"; }
    void g() { std::cout << "g"; }

    template <bool b>
    void call() { (b ? f() : g()); }
};

int main()
{
    A().call<true>();
}

根据 template 传给 call,要么 fg 将被调用。我的问题是,如果编译器以某种方式被迫对if条件进行预评估。考虑一下这个其他可能的实现 call:

template <bool b>
void call() { 
    bool x = b;    
    (x ? f() : g()); 
}

在这种情况下,编译时模板首先被转换为运行时变量,然后才决定是否使用该模板。fg 是做的。我认为,在这种情况下,编译器将无法删除if语句。

事实上,如果我用 榫头 似乎正是这种情况。

标准中是否有某些部分定义了哪些模板表达式? 在编译时评估?

(当然,在这个简单的例子中,我可以很容易地写出针对 b == trueb == false但这不是这个问题的关键。)

c++ metaprogramming template-meta-programming
1个回答
2
投票

所有模板表达式都是在编译时评估的,因为模板在运行时不存在。你可以使用 if constexpr 在编译时,它被认为会被评估。

template <bool b>
void call() { if constexpr (b) f(); else g(); }

在你的例子中(对于 b = true)这将成为

void call() { f(); }

无论优化程度如何。

然而当你使用普通的 if 或三元运算符,生成的代码可能很容易被优化。在您的例子中(同样是针对 b=true)模板实例创建了这样的东西。

void call() { (true ? f() : g()); }

如果你允许的话,编译器可以很容易地优化它。G++与 -O3 例如,只是删除了 A 和呼吁 call 囫囵吞枣 std::cout << "f" 变成 main. 见上 榫头.


凝结。所有模板表达式在编译时都会被评估,但编译器可以识别一个表达式或变量是否是常量,并能够优化这种情况,但编译器没有义务这样做(当你试图调试某些东西时,你不希望优化代码)。

© www.soinside.com 2019 - 2024. All rights reserved.