Consider the following example :
template<int X> class MyClass
{
public:
MyClass(int x) {_ncx = x;}
void test()
{
for (unsigned int i = 0; i < 1000000; ++i) {
if ((X < 0) ? (_cx > 5) : (_ncx > 5)) {
/* SOMETHING */
} else {
/* SOMETHING */
}
}
}
protected:
static const int _cx = (X < 0) ? (-X) : (X);
int _ncx;
};
My question is : will MyClass<-6>::test() and MyClass<6>::test() have a different speed ?
I hope so because in case of a negative template parameter, the if in test function can be evaluated at compile-time, but I’m not sure what is the behaviour of a compiler if there is a compile-time thing and a non-compile-time thing in a ternary operator (which is the case here).
Note : it’s a pure “theoretical” question. If there is a non-null probability of “yes”, I will implement some class for my code with such compile-time template parameters, and if not, I will only provide runtime versions.
For my compiler ( clang++ v2.9 on OS X ) compiling this similar but not identical code:
This generates the following assembly with
clang++ -S -O3.one_fn = do_something<1>
The first functions assembly clearly only has the call to
bar.neg_one_fn = do_something<-1>
The second function has been reduced to a simple if to call either
barorfoo.Summary
So you can see that the compiler inlined the template, then optimised away the branch when it could. So the kind of transformation you are hoping for does occur in current compilers. I got similar results (but less clear assembly) from an old g++ 4.0.1 compiler too.
Addendum:
I decided this example wasn’t quite similar enough to your initial case (as it didnt’ involve the ternary operator) so I changed it to this: (Getting the same kind of results)
This generates the assembly
a() = do_something_else<1>
This still contains the branch.
b() = do_something_else<-1>
Branch is optimised away.