有没有办法扭转#define指令?

在下面的例子中

#define ZERO 0
#define ONE 1
#define TWO 2
#define THREE 3

是否可以从整数2中检索两个?

此示例来自C代码,但是如果需要,我可以使用一些C++代码。我的目标是能够分解这种形式的一些虚假的开关情况循环:
switch(num)
{
   case ZERO:
      return std::to_string(foo.V_ZERO);
   case ONE:
      return std::to_string(foo.V_ONE);
   case TWO:
      return std::to_string(foo.V_TWO);
   case THREE:
      return std::to_string(foo.V_THREE);
}

其中foo是如下结构的实例:
struct Foo
{
   union Val
   {
      int V_ZERO;
      int V_ONE;
      double V_TWO; // nonsense: just to say that types are not the same
      int V_THREE;
   };
};

我的约束如下:
  • 我无法删除#define提供的功能,即我可以编写等效的内容,例如枚举,但我不能丢掉ZERO和0,ONE和1等之间的映射;
  • 现有代码是用C编写的,我无法用C++重写。但是,我可以编写一些补充的C++代码。

  • 我有一些简化代码的想法,但是我想知道是否存在一种众所周知的优雅方法,尤其是通过一些模板或预处理器指令。

    编辑:使用std::to_string表示我对了解如何转换或处理来自 union 的多种类型不感兴趣。

    最佳答案

    如果要自动化某些过程,一种选择是使用xmacros。它们很笨拙,但是取决于您的代码大小,可能会使维护(例如,添加新条目)变得更容易,但会牺牲同事的精力:

    定义xmacro列表:

    #define XLIST(xmacro) \
       xmacro(ZERO, 0) \
       xmacro(ONE, 1) \
       xmacro(TWO, 2) \
       xmacro(THREE, 3) \
    

    然后在需要迭代所有项目时使用它:
    // create an enum containing all items
    #define xmacro(name, value) name,
    enum Item
    {
        XLIST(xmacro)
    };
    #undef xmacro
    
    // get the number of items
    #define xmacro(name, value) +1
    const int NumberOfItems = 0 XLIST(xmacro);
    #undef xmacro
    
    // enum -> value
    int itemToValue(enum Item item)
    {
        switch (item)
        {
            // create a mapping from enum to x
    #define xmacro(name, value) case name: return value;
            XLIST(xmacro)
    #undef xmacro
        }
    
        return -1;
    }
    
    // get enum name
    const char * getItemName(enum Item item)
    {
        switch (item)
        {
            // create a mapping from enum to x
    #define xmacro(name, value) case name: return #name;
            XLIST(xmacro)
    #undef xmacro
        }
    
        return NULL;
    }
    

    这将被预处理成类似:
    enum Item
    {
        ZERO,
        ONE,
        TWO,
        THREE,
    };
    
    const int NumberOfItems = 0 +1 +1 +1 +1; // == 4
    
    int itemToValue(enum Item item)
    {
        switch (item)
        {
            case ZERO: return 0;
            case ONE: return 1;
            case TWO: return 2;
            case THREE: return 3;
        }
    
        return -1;
    }
    
    const char * getItemName(enum Item item)
    {
        switch (item)
        {
            case ZERO: return "ZERO";
            case ONE: return "ONE";
            case TWO: return "TWO";
            case THREE: return "THREE";
    
        }
    
        return NULL;
    }
    

    您可以由此创建几乎任何想要的映射,即对于您的结构,您将使用类似于@Jean-François写道的内容:
    // get struct value by item type
    double getValueByName(enum Item item, struct Foo values)
    {
        switch (item)
        {
            // create a mapping from enum to x
    #define xmacro(name, value) case name: return values.V_##name;
            XLIST(xmacro)
    #undef xmacro
        }
    
        return -1;
    }
    

    10-05 20:49
    查看更多