标准if / else在编译时已知的条件?

时间:2013-07-09 18:22:25

标签: c++ templates optimization if-statement c++11

我知道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的分支吗?它会直接分支到唯一有效的案例吗?

2 个答案:

答案 0 :(得分:6)

优化器将删除未使用分支中的分支和代码,但要注意:编译器需要在优化器甚至有机会查看代码之前处理该函数,这意味着所有分支必须有效(可编译) )对于N的所有值。

例如,如果第二个分支包含:

} else if (N <= 42) {
   char data[50 - N];
// other code

即使优化程序将删除分支,编译器也无法实例化N >= 50的模板。

答案 1 :(得分:2)

我将以下内容输入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)首先不生成死代码的指令。其他编译器可能表现不同。您必须自己测试自己编译器的行为。