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

sha*_*oth 5 c++ macros templates metaprogramming visual-c++

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

#define BINARY_FLAG( n ) ( static_cast<DWORD>( 1 << ( n ) ) )
Run Code Online (Sandbox Code Playgroud)

哪个可以像这样使用("常量"场景):

static const SomeConstant = BINARY_FLAG( 5 );
Run Code Online (Sandbox Code Playgroud)

或者像这样("变量"场景):

for( int i = 0; i < 10; i++ ) {
    DWORD flag = BINARY_FLAG( i );
    // do something with the value
}
Run Code Online (Sandbox Code Playgroud)

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

对于常量场景,我可以使用模板:

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
Run Code Online (Sandbox Code Playgroud)

但这不会用于"变量"场景 - 我需要运行时断言:

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)
Run Code Online (Sandbox Code Playgroud)

后者很好,但没有编译时检查.当然,我希望尽可能进行编译时检查,否则进行运行时检查.在任何时候我都希望尽可能少的运行时开销,所以当可以进行编译时检查时,我不希望进行函数调用(可能不会内联).

我看到了这个问题,但它看起来并不像是同一个问题.

是否有一些构造允许在两者之间交替,这取决于作为标志号传递的表达式是编译时常量还是变量?

iam*_*ind 1

无法参数传递给宏或函数并确定它是编译时常量还是变量。

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