编译器是否强制根据模板参数计算表达式?
Is the compiler forced to evaluate if expressions depending on template parameters?
考虑以下代码片段:
#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>();
}
根据传递给call
的参数template
,将调用f
或g
。我的问题是,编译器是否以某种方式被迫预先评估 if 条件。考虑call
的其他可能实现:
template <bool b>
void call() {
bool x = b;
(x ? f() : g());
}
在这种情况下,编译时模板首先转换为运行时变量,然后再决定f
或g
。我假设在这种情况下编译器将无法删除 if 语句。
事实上,如果我用 godbolt 测试这种行为,那似乎正是发生的事情。
标准的某些部分是否定义了在编译时必须计算哪些模板表达式?
(当然,在这个简单的例子中,我可以很容易地为b == true
和b == false
编写专业,但这不是这个问题的内容。
所有模板表达式都在编译时计算,因为模板在运行时不存在。您可以使用在编译时保证要计算的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()); }
如果您允许,编译器可以轻松优化。例如,带有-O3
的 G++ 只是删除了A
的实例和对call
的调用,只是将std::cout << "f"
移动到main
中。见神电。
Concolusion:所有模板表达式都在编译时计算,但编译器可以识别表达式或变量是否恒定,并且能够优化这种情况,但编译器没有义务这样做(当你尝试调试某些东西时,你不需要优化的代码(
相关文章:
- 模板参数列表中的 false 在模板初始化期间计算为什么?
- 编译器是否强制根据模板参数计算表达式?
- 有没有办法计算函数内arry的长度而不是作为参数传入?
- 返回一个计算了参数的函数
- 术语的计算结果不是采用0个参数的函数
- 错误 C2064:术语的计算结果不是采用 3 个参数的函数
- 错误:一元"*"的类型参数无效(具有"int"):使用 mergesort 计算
- 委派的 ctor 是否受参数计算顺序的影响?
- 函数参数计算顺序与 Lambda 捕获评估顺序
- 大括号和括号之间的参数计算顺序
- 使用引用参数计算函数
- 编译时的模板参数计算
- 在 x86-64 平台上为 C(++) 中的 64 位无符号参数计算 (a*b)%n FAST
- 具有参数计算错误的重载函数
- 模板参数计算
- 根据其他参数计算模板参数的惯用方法
- 移动语义和参数计算顺序
- 惰性参数计算
- C++ 参数计算顺序
- 参数计算和未定义行为