在我使用的外部代码中有枚举:
enum En {VALUE_A, VALUE_B, VALUE_C};
在我使用的另一个外部代码中有3个#define指令:
#define ValA 5
#define ValB 6
#define ValC 7
很多时候我的int X等于ValA或ValB或ValC,我必须将它转换为相应的En值(ValA到VALUE_A,ValB到VALUEB等),因为某些函数签名有enum En。很多时候我必须做相反的操作,将enum En翻译成ValA或ValB或ValC。我不能改变这些函数的签名,并且有很多这样的函数。
问题是:如何翻译?我应该创建2个强制使用的强制转换操作符吗?或者我应该只有两个明确使用的翻译函数:
En ToEn(int)
int FromEn(En)
或其他任何解决方案?
答案 0 :(得分:11)
由于你不能只是在这里投射,我会使用免费功能,如果有可能还需要转换的其他枚举,请尝试使它看起来有点像内置强制转换:
template<typename T>
T my_enum_convert(int);
template<>
En my_enum_convert<En>(int in) {
switch(in) {
case ValA: return VALUE_A;
case ValB: return VALUE_B;
case ValC: return VALUE_C;
default: throw std::logic_error(__FILE__ ": enum En out of range");
}
}
int my_enum_convert(En in) {
switch(in) {
case VALUE_A: return ValA;
case VALUE_B: return ValB;
case VALUE_C: return ValC;
// no default, so that GCC will warn us if we've forgotten a case
}
}
En enumValue = my_enum_convert<En>(ValA);
int hashDefineValue = my_enum_convert(VALUE_A);
enumValue = my_enum_convert<En>(0); // throws exception
或类似的东西 - 如果在使用它时出现问题,可能会调整它。
我不使用隐式转换的原因是已经从En到int的隐式转换,这给出了错误的答案。即使你可以用可以给出正确答案的东西可靠地替换它,结果代码看起来也不会像进行任何转换一样。 IMO这会阻碍后来查看代码而不是键入转换例程的任何人会阻碍你。
如果要转换为int并从int转换为非常不同,那么您可以将模板和函数设置为不同的名称。
或者,如果您希望它们看起来相同(更像是static_cast),您可以这样做:
template<typename T>
T my_enum_convert(En in) {
switch(in) {
case VALUE_A: return ValA;
case VALUE_B: return ValB;
case VALUE_C: return ValC;
}
}
int hashDefineValue = my_enum_convert<int>(VALUE_A);
如上所述,T必须从int进行隐式转换。如果您想支持只有显式转换的T,请使用“return T(ValA);”而是(或者“返回static_cast&lt; T&gt;(ValA);”,如果你认为单个arg构造函数是C风格的强制转换,因此是不允许的。)
答案 1 :(得分:2)
虽然隐式转换比转换函数更方便,但看到发生的事情也不太明显。 一种既方便又明显的方法可能是使用自己的类和重载的转换运算符。 将自定义类型转换为枚举或int时,忽略某些自定义转换并不容易。
如果为此创建一个类不是出于任何原因的选项,我会选择翻译函数,因为在编写代码时,维护期间的可读性比方便更重要。
答案 2 :(得分:1)
有函数然后重载库函数吗?
//libFunc( enum a );
libFuncOverload( define a ) {
libFunc( toEn( a ) );
}
答案 3 :(得分:1)
您不能为枚举重载运算符。或者我错过了什么? 好吧,你可以创建一些虚拟类,它们会有一个带有int的隐式构造函数,然后有一个强制转换运算符到枚举(反之亦然)。
因此,唯一的解决方案是拥有功能。另外,我会像帕特里克所说的那样做出过载。
答案 4 :(得分:-1)
转换 enum-to-int ,例如int(VALUE_A),自动/透明地发生。
转换 int-to-enum ,例如 En(ValA),可以从健全性检查中受益,以确保 int 值是枚举的有效成员。(虽然希望库代码不会假设它的 enum 值首先是有效的。)
虽然它对“ int x ”案例没有帮助,但您可以通过更改来帮助:
#define ValA 5
要:
#define ValA VALUE_A
提供枚举En()在任何地方都包含/定义, ValA 和 VALUE_A 将适用于< strong> both foo(int)和 bar(En) 无处不在自动/透明。
您可以使用:
#ifdef ValA
STATIC_ASSERT( ValA == VALUE_A, ValA_equal_VALUE_A );
#undef ValA
#else
#warning "ValA undefined. Defining as VALUE_A"
#endif
#define ValA VALUE_A
STATIC_ASSERT 类似于:
/* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4( a,b,c,d) CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d) a ## b ## c ## d
/* Creates a typedef that's legal/illegal depending on EXPRESSION. *
* Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*". *
* (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT) \
typedef char CONCATENATE_4( static_assert____, IDENTIFIER_TEXT, \
____failed_at_line____, __LINE__ ) \
[ (EXPRESSION) ? 1 : -1 ]