Here's my problem. I have a BINARY_FLAG
macro:
#define BINARY_FLAG( n ) ( static_cast<DWORD>( 1 << ( n ) ) )
Which can be used either like this ("constant" scenario):
static const SomeConstant = BINARY_FLAG( 5 );
or like this ("variable" scenario):
for( int i = 0; i < 10; i++ ) {
DWORD flag = BINARY_FLAG( i );
// do something with the value
}
This macro is not foolproof at all - one can pass -1
or 34
there and there will at most be a warning yet behavior will be undefined. I'd like to make it more foolproof.
For the constant scenario I could use a template:
template<int Shift> class BinaryFlag {
staticAssert( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
public:
static const DWORD FlagValue = static_cast<DWORD>( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag<n>::FlagValue
but this will not go for the "variable" scenario - I'd need a runtime assertion there:
inline DWORD ProduceBinaryFlag( int shift )
{
assert( 0 <= shift && shift < sizeof( DWORD) * CHAR_BIT );
return static_cast<DWORD>( 1 << shift );
}
#define BINARY_FLAG( n ) ProduceBinaryFlag(n)
The latter is good, but has no compile-time checks. Of course, I'd like a compile-time check where possible and a runtime check otherwise. At all times I want as little runtime overhead as possible so I don't want a function call (that maybe won't be inlined) when a compile-time check is possible.
I saw this question, but it doesn't look like it is about the same problem.
Is there some construct that would allow to alternate between the two depending on whether the expression passed as a flag number is a compile-time constant or a variable?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…