编译时已知条件下的标准if/else
Standard if/else on conditions known at compile-time?
我知道C++中的一些元编程技术,可以在编译时计算常量。元函数中的大部分时间分支是通过三元运算符完成的,与标准if/else相反,三元运算符可以在编译时进行求值。
但关于这类功能:
template <unsigned int N>
void f()
{
if (N == 0) {
// Some computations here
} else if (N <= 42) {
// Some computations here
} else {
// Some computations here
}
}
编译器将做什么(假设-O3
)?编译器知道f<0>()
在第一种情况下总是分支,f<32>()
在第二种情况下始终分支,而f<64>()
在第三种情况下一直分支。
编译器会删除始终为false
的分支吗?它会直接分支到唯一有效的案例吗?
优化器将删除分支和未使用的分支中的代码,但要注意:编译器需要在优化器有机会查看代码之前处理函数,这意味着所有分支对于N
的所有值都必须是有效的(可编译的)。
例如,如果第二个分支包含:
} else if (N <= 42) {
char data[50 - N];
// other code
编译器将无法实例化N >= 50
的模板,即使优化器将删除该分支。
我在http://gcc.godbolt.org/,是一个显示生成的程序集的联机编译器。您可以将自己的编译器与它支持的任何开关一起使用,以输出程序集。
volatile int i;
template <unsigned int N>
void f()
{
if (N == 0) {
i = 1;
} else if (N <= 42) {
i = 2;
} else {
i = 3;
}
}
template void f<0>();
template void f<10>();
template void f<100>();
这是我拿到的
void f<0u>(): # @void f<0u>()
movl $1, i
ret
void f<10u>(): # @void f<10u>()
movl $2, i
ret
void f<100u>(): # @void f<100u>()
movl $3, i
ret
i:
.long 0 # 0x0
正如您所看到的,每个实例化都删除了所有的死代码。
事实上,此代码是在禁用优化的情况下生成的;我使用的编译器(clang)一开始并没有为死代码生成指令。其他编译器的行为可能有所不同。您必须自己测试编译器的行为。
相关文章:
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何删除peer if else分支中的冗长句子
- "complicated-nested" "for/if statement"真的遵循C标准吗?
- 标准对单个 if 语句中单个变量的双重比较有什么看法
- 编译时已知条件下的标准if/else
- "if (getline(fin, str)) {}" 是否符合 C++11 标准?