有没有办法扭转#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;
};
};
我的约束如下:
我有一些简化代码的想法,但是我想知道是否存在一种众所周知的优雅方法,尤其是通过一些模板或预处理器指令。
编辑:使用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;
}