如何一致地定义可同时作为enum、int和string使用的选项列表
How to consistently define list of options to use as enum, int and string at the same time?
我提供了一个显示分辨率的例子,但问题更普遍。
假设我们有以下配置:640x480;1024 x768;1600 x900分辨率下玩。如果它们是分开定义的,它看起来像:
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++工具有两种不同的方法来解决这类问题(它们都使用预处理器的宏):
- 基于可变宏的方法(您可以编写自己的代码或使用Boost)。预处理器库宏).
- 基于x -宏技术的方法
如果您使用c++ 03或更低版本,则第二种方法适用于您(如果您使用c++ 11或更高版本,或者您的c++编译器支持C99,则第一种方法可用)。下面是它的描述:
-
创建一个包含文件,不包含保护(你可以给它一个不同于你通常的头文件扩展名,例如
inc
),名称为Resolution
,内容如下: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"
.
如果您不习惯使用enum
,您可以使用以下内容:
#define CONCAT2(A, B) A ## B
#define CONCAT(A, B) CONCAT2(A, B)
#define STR2(A) #A
#define STR(A) STR2(A)
#define DEFINE_RESOLUTION(ResClass, X, Y)
struct ResClass {
static const int val = CONCAT(0x, CONCAT(X, Y));
static char const* toString()
{
return STR(CONCAT(X, CONCAT(x, Y)));
}
static int getX() { return (X); }
static int getY() { return (Y); }
};
DEFINE_RESOLUTION(Res1, 640, 480);
DEFINE_RESOLUTION(Res2, 1024, 768);
// Test the code
#include <iostream>
int getint()
{
return Res1::val;
// return Res2::val;
}
int main()
{
int v = getint();
switch (v)
{
case Res1::val:
std::cout << Res1::getX() << "n";
std::cout << Res1::getY() << "n";
std::cout << Res1::toString() << "n";
break;
case Res2::val:
std::cout << Res2::getX() << "n";
std::cout << Res2::getY() << "n";
std::cout << Res2::toString() << "n";
break;
default:
std::cout << "Got defaultn";
}
return 0;
}
输出:640
480
640x480
相关文章:
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 两个数组,int 和 string,如何显示带有对应 int 的字符串?
- <string> 如何在使用 SWIG 时将 int 数组和 List 作为参数传递给 C# C++
- OpenCV undefined reference to 'cv::imread(cv::String const&, int)'
- map<string, int> m= {}; 在C++中是什么意思?
- 如何从map<pair<string,int>,pair<string,Array>>中迭代和查找?
- C++将文件行分离为String和Int
- 与 string.size() 比较时 int 的符号性显示警告
- freq_table[field_pm_value] = map<string, int>(); 是什么意思?
- 将 int 附加到 std::string
- 方括号在"map <string, int> instance[numberFeatures];"中是什么意思
- 如何使用单 for 循环遍历 std::map<string>int 和 std::vector<int>?
- 为什么一个简单的bimap(std::string <-> int)不起作用?
- 在 QString 中连接 stl string+int+int+int
- Boost lexical_cast<std::string>(int) MSVC 2008 bug
- 从文件中读取数据类型string, int double.将每一行数据放入对象向量中
- 如何返回包含string/int变量的字符串
- 如何从键盘中读取包含c-string, int和float的结构变量
- 创建string+int set stl类型
- c++ string (int) + string (int)