且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我的代码如何告诉编译时常数与变量?

更新时间:2022-10-14 21:42:41

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

***的方法是你用 #define BINARY_FLAG(n)编译时代码,把宏放在任何地方,然后编译它。在 n 将要运行时,将会收到编译器错误。现在,您可以使用运行时宏 BINARY_FLAG_RUNTIME(n)替换这些宏。这是唯一可行的方法。


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?

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.