Вот мой проблема. У меня есть макрос BINARY_FLAG
:
#define BINARY_FLAG( n ) ( static_cast( 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 class BinaryFlag {
staticAssert( 0 <= Shift && Shift < sizeof( DWORD) * CHAR_BIT );
public:
static const DWORD FlagValue = static_cast( 1 << Shift );
};
#define BINARY_FLAG( n ) CBinaryFlag::FlagValue
, но он не пойдет для «переменного» сценария - мне понадобится утверждение времени выполнения:
inline DWORD ProduceBinaryFlag( int shift )
{
assert( 0 <= shift && shift < sizeof( DWORD) * CHAR_BIT );
return static_cast( 1 << shift );
}
#define BINARY_FLAG( n ) ProduceBinaryFlag(n)
Последний вариант хорош, но не требует проверок во время компиляции. Конечно, мне бы хотелось, чтобы по возможности выполнялась проверка во время компиляции, а в противном случае - проверка во время выполнения. Я всегда хочу как можно меньше накладных расходов во время выполнения, поэтому я не хочу вызова функции (которая, возможно, не будет встроена), когда возможна проверка во время компиляции.
Я видел этот вопрос , но не похоже, что это одна и та же проблема.
Есть ли какая-нибудь конструкция, которая позволяла бы переключаться между ними в зависимости от того, является ли выражение, переданное как номер флага, константой времени компиляции или переменной ?