是否可以手动定义枚举类的转换?

时间:2012-10-05 20:24:27

标签: c++ enums c++11 enum-class

通常,您可以使用以下语法为类定义强制转换:

class Test {
public:
  explicit operator bool() { return false; }
};

enum class

有没有办法做到这一点或类似的事情?

3 个答案:

答案 0 :(得分:20)

不,不是。

实际上,enum class根本就没有课程。仅使用class关键字,因为突然将未范围的enum更改为范围enum将意味着重新所有枚举代码。因此,委员会决定区分新风格和旧风格的枚举,新标记将使用class进行标记,因为它已经是一个关键字,因此enum无法命名为class在C ++中。他们本可以选择另一个,无论如何都不会有更多的意义。

然而,尽管有class个关键字,它们仍然是常规枚举,因为在括号内只允许使用枚举数(以及分配给它们的可能值)。

答案 1 :(得分:14)

不,但您可以使用constexpr成员和构造函数使普通类类型像枚举类一样运行。然后,您可以添加所需的所有其他成员函数。


证明即使使用switch也能正常工作:

#include <iostream>

struct FakeEnum
{
    int x;

    constexpr FakeEnum(int y = 0) : x(y) {}

    constexpr operator int() const { return x; }

    static const FakeEnum A, B, Z;
};

constexpr const FakeEnum FakeEnum::A{1}, FakeEnum::B{2}, FakeEnum::Z{26};

std::istream& operator>>(std::istream& st, FakeEnum& fe)
{
    int val;
    st >> val;
    fe = FakeEnum{val};
    return st;
}

int main()
{
    std::cout << "Hello, world!\n";
    FakeEnum fe;
    std::cin >> fe;

    switch (fe)
    {
        case FakeEnum::A:
        std::cout << "A\n";
        break;
        case FakeEnum::B:
        std::cout << "B\n";
        break;
        case FakeEnum::Z:
        std::cout << "Z\n";
        break;
    }
}

证明使用switch不需要与int进行隐式互换:

#include <iostream>

/* pseudo-enum compatible with switch and not implicitly convertible to integral type */
struct FakeEnum
{
    enum class Values { A = 1, B = 2, Z = 26 };
    Values x;

    explicit constexpr FakeEnum(int y = 0) : FakeEnum{static_cast<Values>(y)} {}
    constexpr FakeEnum(Values y) : x(y) {}

    constexpr operator Values() const { return x; }
    explicit constexpr operator bool() const { return x == Values::Z; }

    static const FakeEnum A, B, Z;
};

constexpr const FakeEnum FakeEnum::A{Values::A}, FakeEnum::B{Values::B}, FakeEnum::Z{Values::Z};

std::istream& operator>>(std::istream& st, FakeEnum& fe)
{
    int val;
    st >> val;
    fe = FakeEnum(val);
    return st;
}

int main()
{
    std::cout << "Hello, world!\n";
    FakeEnum fe;
    std::cin >> fe;

    switch (fe)
    {
        case FakeEnum::A:
        std::cout << "A\n";
        break;
        case FakeEnum::B:
        std::cout << "B\n";
        break;
        case FakeEnum::Z:
        std::cout << "Z\n";
        break;
    }
    // THIS ERRORS: int z = fe;
}

答案 2 :(得分:4)

您无法在C ++中定义非成员转换运算符。你当然不能定义枚举的成员函数。 因此,我建议您使用自由函数将枚举转换为其他类型,就像实现强制转换运算符一样。

e.g。

bool TestToBool(enum_e val)
{
    return false;
}

const char *TestToString(enum_e val)
{
    return "false";
}

有一种将这些枚举与bool相关联的好方法,你必须将它分成两个文件.h和.cpp。 这是有帮助的:

enum.h

///////////////////////////////
// enum.h
#ifdef CPP_FILE
#define ENUMBOOL_ENTRY(A, B)            { (enum_e) A, (bool) B },
struct EnumBool
{
    enum_e  enumVal;
    bool    boolVal;
};
#else
#define ENUMBOOL_ENTRY(A, B)            A,
#endif


#ifdef CPP_FILE
static EnumBool enumBoolTable[] = {
#else
enum enum_e
{
#endif
ENUMBOOL_ENTRY(ItemA, true),
ENUMBOOL_ENTRY(ItemB, false),
...
};

bool EnumToBool(enum_e val);

enum.cpp

///////////////////////////////
// enum.cpp
#define CPP_FILE
#include "enum.h"

bool EnumToBool(enum_e val)
    //implement

我没有编译它,所以如果它有任何错误,请放轻松:)。