对于我的编译器( OS X 上的 clang++ v2.9 )编译这个相似但不相同的代码:
void foo();
void bar();
template<int N>
void do_something( int arg ) {
if ( N<0 && arg<0 ) { foo(); }
else { bar(); }
}
// Some functions to instantiate the templates.
void one_fn(int arg) {
do_something<1>(arg);
}
void neg_one_fn(int arg) {
do_something<-1>(arg);
}
这将生成以下程序集clang++ -S -O3
。
one_fn = do_something<1>
第一个函数程序集显然只有对bar
.
.globl __Z6one_fni
.align 4, 0x90
__Z6one_fni: ## @_Z6one_fni
Leh_func_begin0:
pushl %ebp
movl %esp, %ebp
popl %ebp
jmp __Z3barv ## TAILCALL
Leh_func_end0:
neg_one_fn = do_something<-1>
第二个函数已简化为一个简单的 if 调用bar
or 或foo
。
.globl __Z10neg_one_fni
.align 4, 0x90
__Z10neg_one_fni: ## @_Z10neg_one_fni
Leh_func_begin1:
pushl %ebp
movl %esp, %ebp
cmpl $0, 8(%ebp)
jns LBB1_2 ## %if.else.i
popl %ebp
jmp __Z3foov ## TAILCALL
LBB1_2: ## %if.else.i
popl %ebp
jmp __Z3barv ## TAILCALL
Leh_func_end1:
概括
所以你可以看到编译器内联了模板,然后尽可能优化了分支。因此,您希望的那种转换确实发生在当前的编译器中。我也从旧的 g++ 4.0.1 编译器得到了类似的结果(但汇编不太清楚)。
附录:
我认为此示例与您的初始情况不太相似(因为它不涉及三元运算符)所以我将其更改为:(获得相同的结果)
template<int X>
void do_something_else( int _ncx ) {
static const int _cx = (X<0) ? (-X) : (X);
if ( (X < 0) ? (_cx > 5) : (_ncx > 5)) {
foo();
} else {
bar();
}
}
void a(int arg) {
do_something_else<1>(arg);
}
void b(int arg) {
do_something_else<-1>(arg);
}
这会生成程序集
a() = do_something_else<1>
这仍然包含分支。
__Z1ai: ## @_Z1ai
Leh_func_begin2:
pushl %ebp
movl %esp, %ebp
cmpl $6, 8(%ebp)
jl LBB2_2 ## %if.then.i
popl %ebp
jmp __Z3foov ## TAILCALL
LBB2_2: ## %if.else.i
popl %ebp
jmp __Z3barv ## TAILCALL
Leh_func_end2:
b() = do_something_else<-1>
分支被优化掉了。
__Z1bi: ## @_Z1bi
Leh_func_begin3:
pushl %ebp
movl %esp, %ebp
popl %ebp
jmp __Z3barv ## TAILCALL
Leh_func_end3: