我提供了一个显示分辨率的示例,但问题更为笼统。
假设我们有以下配置:640x480; 1024x768; 1600x900。如果它们是单独定义的,它看起来像:
std::string RESTR[] = { "640x480", "1024x768", "1600x900" };
struct Enum { enum ERes { _640x480, _1024x768, _1600x900 }; };
uint RES[][2] = { { 640, 480 }, { 1024, 768 }, { 1600, 900 } };
维护所有列表太容易出错。它应该以下列方式给出(或至少是非常相似的方式):
Res( 640, 480 )
Res( 1024, 768 )
Res( 1600, 900 )
Resolution 类似乎是一个很好的解决方案,它在需要时表现为一个字符串,并在其他用例中返回一个值。但是在运行应用程序之前它没有枚举。为了在开发中使用解析枚举,需要编译时魔法、预处理器或模板定义。如何解决?
是否有针对此类问题的标准最先进方法?
最佳答案
有两种不同的方法可以仅使用 C++ 工具来解决此类问题(它们都使用预处理器的宏):
- 基于 variadic macro 的方法(您可以编写自己的代码或使用 Boost.Preprocessor 库宏)。
- 基于 X-macro technique 的方法.
如果您使用 C++03 或更低版本,则第二种方法适合您(如果您使用 C++11 或更高版本,或者如果您的 C++ 编译器支持 C99,则第一种方法可用)。这是它的描述:
创建一个包含文件没有包含保护(你可以给它一个不同于你通常的头文件扩展名的扩展名,例如
inc
),名称为决议
及以下内容:RESOLUTION( 640, 480 ) RESOLUTION( 1024, 768 ) RESOLUTION( 1600, 900 )
按如下方式定义数组:
#define TO_STRING_LITERAL_(S) #S #define TO_STRING_LITERAL(S) TO_STRING_LITERAL_(S) #define STRING_RESOLUTION_(X, Y) X ## x ## Y #define STRING_RESOLUTION(X, Y) TO_STRING_LITERAL(STRING_RESOLUTION_(X, Y)), #define ENUM_RESOLUTION(X, Y) _ ## X ## x ## Y, #define INT_RESOLUTION(X, Y) { X , Y }, #define RESOLUTION(X, Y) STRING_RESOLUTION(X, Y) std::string RESTR[] = { # include "Resolution.inc" }; #undef RESOLUTION #define RESOLUTION(X, Y) ENUM_RESOLUTION(X, Y) struct Enum { enum ERes { # include "Resolution.inc" }; }; #undef #define RESOLUTION(X, Y) INT_RESOLUTION(X, Y) uint RES[][2] = { # include "Resolution.inc" }; #undef
更新: @rici在评论中建议对 STRING_RESOLUTION
宏进行有趣的简化:
#define STRING_RESOLUTION(X, Y) #X "x" #Y
这是可能的,因为一系列字符串文字被 C++ 编译器识别为一个文字:"string1""string2""string3"== "string1string2string3"
。
关于c++ - 如何一致地定义同时用作枚举、整数和字符串的选项列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33131374/