Here\'s my problem. I have a BINARY_FLAG
macro:
#define BINARY_FLAG( n ) ( static_cast( 1 << ( n ) ) )
Whic
This is simpler than you think :)
Let's have a look:
#include <cassert>
static inline int FLAG(int n) {
assert(n>=0 && n<32);
return 1<<n;
}
int test1(int n) {
return FLAG(n);
}
int test2() {
return FLAG(5);
}
I don't use MSVC, but I compiled with Mingw GCC 4.5:
g++ -c -S -O3 08042.cpp
The resulting code for first method looks like:
__Z5test1i:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl 8(%ebp), %ecx
cmpl $31, %ecx
ja L4
movl $1, %eax
sall %cl, %eax
leave
ret
L4:
movl $4, 8(%esp)
movl $LC0, 4(%esp)
movl $LC1, (%esp)
call __assert
.p2align 2,,3
And the second:
__Z5test2v:
pushl %ebp
movl %esp, %ebp
movl $32, %eax
leave
ret
See? The compiler is smart enough to do it for you. No need for macros, no need for metaprogramming, no need for C++0x. As simple as that.
Check if MSVC does the same... But look - it's really easy for the compiler to evaluate a constant expression and drop the unused conditional branch. Check it if you want to be sure... But generally - trust your tools.
I suggest you use two macros. BINARY_FLAG CONST_BINARY_FLAG That will make your code easier to grasp for others. You do know, at the time of writing, if it is a const or not. And I would in no case worry about runtime overhead. Your optimizer, at least in VS, will sort that out for you.
It's not possible to pass an argument to a macro or function and determine if it's compile time constant or a variable.
The best way is that you #define BINARY_FLAG(n)
with compile time code and place that macro everywhere and then compile it. You will receive compiler-errors at the places where n
is going to be runtime. Now, you can replace those macros with your runtime macro BINARY_FLAG_RUNTIME(n)
. This is the only feasible way.