我的代码如何区分编译时常量和变量?

这是我的问题.我有一个 BINARY_FLAG 宏:

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
}

这个宏根本不是万无一失的――你可以通过 -134 那里最多会有一个警告,但行为将是未定义的.我想让它更万无一失.

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?

推荐答案

不可能将参数传递给宏或函数并确定它是编译时常量还是变量.

It's not possible to pass an argument to a macro or function and determine if it's compile time constant or a variable.

最好的方法是您#define BINARY_FLAG(n) 使用编译时代码并将该宏放置在任何地方,然后编译它.您将在 n 将成为运行时的地方收到编译器错误.现在,您可以使用运行时宏 BINARY_FLAG_RUNTIME(n) 替换这些宏.这是唯一可行的方法.

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.

相关文章