enum-int casting:运算符或函数

时间:2008-12-15 09:08:54

标签: c++ enums casting

在我使用的外部代码中有枚举:

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)

或其他任何解决方案?

5 个答案:

答案 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 ]