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)
这个宏根本不是万无一失的 - 一个人可以通过-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
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)
后者很好,但没有编译时检查.当然,我希望尽可能进行编译时检查,否则进行运行时检查.在任何时候我都希望尽可能少的运行时开销,所以当可以进行编译时检查时,我不希望进行函数调用(可能不会内联).
我看到了这个问题,但它看起来并不像是同一个问题.
是否有一些构造允许在两者之间交替,这取决于作为标志号传递的表达式是编译时常量还是变量?
无法将参数传递给宏或函数并确定它是编译时常量还是变量。
最好的方法是使用#define BINARY_FLAG(n)
编译时代码并将该宏放置在各处,然后编译它。n
您将在运行时的地方收到编译器错误。现在,您可以将这些宏替换为运行时宏BINARY_FLAG_RUNTIME(n)
。这是唯一可行的办法。