C++元编程,使用switchcase设置和获取成员变量

C++ metaprograming to set and get member variables using switch case

本文关键字:获取 成员 变量 设置 switchcase 编程 使用 C++      更新时间:2023-10-16

比方说,我有一个类,它可以有很多变量。这些变量中的每一个都将有一个唯一的枚举映射到它。我想使用switch case为变量设置/获取值。我不想为每个变量写每个时间的"case",而是希望有一个扩展到set/get函数和相应开关case的宏。

class myClass
{
  int m_i, m_j;
  void Set(int variable, int i);
  void Get(var variable, int& i);
};
enum var{ VAR_I, VAR_J };
//..........cpp.........
//here I will map enum to member variables
//so if i write this.
//
VARIABLE_START(myClass)
  VARIABLE(VAR_I, m_i)
  VARIABLE(VAR_J, m_j)
VARIABLE_END
//it should expand to....
void myClass::Set(var variable, int i)
{
   switch(var)
   {
      case VAR_I: ....
          break;
      case VAR_J: ....
          break;
  }
}
void myClass::Get(var variable, int& i)
{
   switch(var)
   {
      case VAR_I: ....
          break;
      case VAR_J: ....
          break;
  }
}

现在,我在定义这些宏时遇到了问题,这些宏应该扩展到两个(或多个)成员函数,每个成员变量都有切换情况。任何形式的帮助都将不胜感激。

对于预处理器方法,请考虑使用X-Macros:

#define APPLY_MY_VARIABLES 
    MY_VARIABLES(m_i, VAR_I) 
    MY_VARIABLES(m_j, VAR_J)
enum var {
#define MY_VARIABLES(VAR, ENUM) ENUM ,
    APPLY_MY_VARIABLES
#undef  MY_VARIABLES
    // NOTE: The above emits a trailing comma; that's allowed.
    // You may also add another enumerator you can use as a count.
};
class myClass
{
#define MY_VARIABLES(VAR, ENUM) int VAR;
    APPLY_MY_VARIABLES
#undef  MY_VARIABLES
   void Set(var variable, int i);
   void Get(var variable, int& i);
};
void myClass::Set(var variable, int i)
{
   switch(var)
   {
   default: ...
#define MY_VARIABLES(VAR,ENUM) 
      case ENUM: 
          VAR = i; 
          break;
      APPLY_MY_VARIABLES
#undef  MY_VARIABLES
  }
}
void myClass::Get(var variable, int& i)
{
   switch(var)
   {
      default: ...
#define MY_VARIABLES(VAR, ENUM) 
      case ENUM: 
          i = VAR; 
          break;
      APPLY_MY_VARIABLES
#undef  MY_VARIABLES
  }
}

关键是要创建一个令牌的"关系"——这是一种用所需数据实例化对宏的多个调用的方法,但要保留未定义的宏。在这里,关联是用一个主宏创建的——应用宏。

在使用时,您可以将宏定义为根据特定目的进行扩展,然后使用主宏应用关系本身。展开后,应该立即取消内部宏的定义(就像关闭for循环一样)。

另一种方法是通过将内部宏放在一个单独的文件中来建立关联:

foo.def

MY_VARIABLES(m_i, VAR_I)
MY_VARIABLES(m_j, VAR_J)

这个文件就变成了关系。在这种情况下的应用是通过包括以下文件来完成的:

class myClass
{
#define MY_VARIABLES(VAR, ENUM) int VAR;
#include "foo.def"
#undef  MY_VARIABLES
   void Set(var variable, int i);
   void Get(var variable, int& i);
};

以下是@NickyC提示的那种无宏解决方案的草图在:

// myClass,h
#include <map>
enum var{ VAR_I, VAR_J };
struct myClass
{
    int m_i, m_j;
    void Set(var variable, int i) {
        (this->*map[variable]) = i;
    }
    void Get(var variable, int& i) const {
        i = (this->*map[variable]);
    }
private:
    static std::map<var,int myClass::*> map;
};
// myClass.cpp
std::map<var,int myClass::*> myClass::map = {
    { VAR_I, &myClass::m_i },
    { VAR_J, &myClass::m_j }
};

它依赖于将var值映射到myClass的成员。为了测试,附加:

#include <iostream>
using namespace std;
int main()
{
    myClass mc;
    mc.Set(VAR_I,2);
    mc.Set(VAR_J,4);
    int i, j;
    mc.Get(VAR_I,i);
    mc.Get(VAR_J,j);
    cout << i << 'n' << j << endl;
    return 0;
}

输出:

2
4

顺便注意一下:

    void Get(var variable, int& i) const {
        i = (this->*map[variable]);
        // or whatever
    }

很可能不如方便

    int const & Get(var variable) const {
        return (this->*map[variable]);
        // or whatever
    }

(gcc 4.9.2,-std=c++11)