让我们说,我有一个类,它可以有很多变量。每个变量都有一个映射到它的唯一枚举。我想使用switch case为变量设置/获取值。而不是每次写作" case"对于每个变量,我想要宏扩展到set / get函数和相应的switch 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;
}
}
现在我在定义这些宏时面临问题,这些宏应该扩展为两个(或更多)成员函数,每个成员变量都有switch case。 任何形式的帮助表示赞赏。
答案 0 :(得分:1)
对于预处理器方法,请考虑使用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);
};
答案 1 :(得分:1)
这是@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)