c++ - 如何一致地定义同时用作枚举、整数和字符串的选项列表?

标签 c++ templates type-conversion c-preprocessor compile-time

我提供了一个显示分辨率的示例,但问题更为笼统。

假设我们有以下配置: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++ 工具来解决此类问题(它们都使用预处理器的宏):

  1. 基于 variadic macro 的方法(您可以编写自己的代码或使用 Boost.Preprocessor 库宏)。
  2. 基于 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/

相关文章:

c++ - 渲染目标 ID2D1Bitmap 错误

c++ - 如何在 gcc 错误消息中隐藏默认模板参数?

c++ - 从模板中使用的结构类型中查找类型(可能是底层的)

c++ - 如何将 int 转换为 QString?

c - iphone:如果 float 为负数,则转换为无符号整数的 float 将设置为 0?

c# - 从 C++ 调用 C#,C# 命名空间中的 "."有困难

c++ - 选择适当的FIFO数据结构

c++ - 使用 `A<int>::template B<int> x;` 定义变量是否符合 C++ 标准?

templates - JSF/PrimeFaces - <p :layout> 的模板

c++ - C/C++如何调用外部程序并获取多个返回值?