Ham*_*jan 3 c++ macros metaprogramming bit-fields
目标是控制允许哪些类型的用户在UI级别执行哪些操作.这段代码已经存在了一段时间; 我只想稍微改进一下.我试图改进的文件可能应该是自动生成的,但是这个变化太大了,所以我寻求一个更简单的解决方案.
我们将调用的文件PermissionBits.h有一堆这样的:
// Here names are mangled; for example XYZ_OP_A is:
// permission to operation A in category/context XYZ
// SCU64 = static const unsigned __int64
// Some namespaces utilize all 64 bits
// The actual values (as long as they are proper bit fields)
// do not matter - they are always used by name
namespace XYZPermissionBits
{
SCU64 XYZ_OP_A = 1UI64 << 0; // 1 = 0x0000000000000001
SCU64 XYZ_OP_B = 1UI64 << 1; // 2 = 0x0000000000000002
SCU64 XYZ_OP_C = 1UI64 << 2; // 4 = 0x0000000000000004
SCU64 XYZ_OP_C = 1UI64 << 3; // 8 = 0x0000000000000008
SCU64 XYZ_OP_D = 1UI64 << 4; // 16 = 0x0000000000000010
SCU64 XYZ_OP_E = 1UI64 << 5; // 32 = 0x0000000000000020
SCU64 XYZ_OP_F = 1UI64 << 6; // 64 = 0x0000000000000040
SCU64 XYZ_OP_G = 1UI64 << 7; // 128 = 0x0000000000000080
SCU64 XYZ_OP_H = 1UI64 << 8; // 256 = 0x0000000000000100
SCU64 XYZ_OP_I = 1UI64 << 9; // 512 = 0x0000000000000200
SCU64 XYZ_OP_J = 1UI64 << 10; // 1024 = 0x0000000000000400
SCU64 XYZ_OP_K = 1UI64 << 11; // 2048 = 0x0000000000000800
SCU64 XYZ_OP_L = 1UI64 << 12; // 4096 = 0x0000000000001000
}
Run Code Online (Sandbox Code Playgroud)
即使在1UI64 << <numBits>;快捷方式的帮助下仍然存在问题,因为编码器会创建具有重复值的标记,进行拼写错误等.
理想情况下,我想要一个可以很好地格式化的宏,看起来像:
BITFIELDS_FOR_NAMESPACE(
//*************** <<== I want to make the namespace name more vivid
XYZPermissionBits,
//*************** <<== somehow if that is possible. It is not a must-have.
XYZ_OP_A, // Being able to add a comment here would be nice, but not critical
XYZ_OP_B,
XYZ_OP_C,
XYZ_OP_D,
XYZ_OP_E,
XYZ_OP_F,
XYZ_OP_G,
XYZ_OP_H,
XYZ_OP_I,
XYZ_OP_J,
XYZ_OP_K,
XYZ_OP_L
)
Run Code Online (Sandbox Code Playgroud)
我希望这个宏是灵活的,并防止我输入少于2个或超过65个参数 - 命名空间名称+ 64个标志.是可以做我想要的或接近它,还是应该使用生成的代码?您有什么其他建议吗?
使用Boost.PreProcessor测试的示例:
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/comparison/greater.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/debug/assert.hpp>
#include <boost/preprocessor/seq/size.hpp>
#define CHECK_SIZE(size) \
BOOST_PP_ASSERT_MSG(BOOST_PP_GREATER(size, 1), "< 2 :(") \
BOOST_PP_ASSERT_MSG(BOOST_PP_LESS(size, 65), "> 64 :(") \
#define DO_MAKE_BITFIELDS(a, b, i, elem) \
SCU64 elem = 1UI64 << i;
#define BITFIELDS_FOR_NAMESPACE(name, seq) \
CHECK_SIZE(BOOST_PP_SEQ_SIZE(seq)) \
namespace name { \
BOOST_PP_SEQ_FOR_EACH_I(DO_MAKE_BITFIELDS, _, seq) \
}
Run Code Online (Sandbox Code Playgroud)
用法:
BITFIELDS_FOR_NAMESPACE(
XYZPermissionBits,
(XYZ_OP_A)
(XYZ_OP_B)
// ...
);
Run Code Online (Sandbox Code Playgroud)