Вот моя проблема. У меня есть BINARY_FLAG
макрос:
#define BINARY_FLAG( n ) ( static_cast<DWORD>( 1 << ( n ) ) )
Который может использоваться как этот (сценарий "константы"):
static const SomeConstant = BINARY_FLAG( 5 );
или как это (сценарий «переменной»):
for( int i = 0; i < 10; i++ ) {
DWORD flag = BINARY_FLAG( i );
// do something with the value
}
Этот макрос вообще не защищен от дурака - туда можно передать -1
или 34
, и самое большее будет предупреждение, но поведение будет неопределенным. Я бы хотел сделать его более надежным.
Для постоянного сценария я мог бы использовать шаблон:
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
но это не относится к «переменному» сценарию - мне нужно утверждение там во время выполнения:
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)
Последнее хорошо, но не проверяет время компиляции. Конечно, я хотел бы проверить во время компиляции, где это возможно, и проверку во время выполнения в противном случае. Я всегда хочу как можно меньше накладных расходов во время выполнения, поэтому я не хочу вызова функции (которая, возможно, не будет встроена), когда возможна проверка во время компиляции.
Я видел этот вопрос , но это не похоже на ту же проблему.
Существует ли какая-либо конструкция, которая позволяла бы чередовать их в зависимости от того, является ли выражение, переданное в виде числа флага, константой времени компиляции или переменной?