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

C++ 是否可以手动定义枚举类的转换?,c++,enums,c++11,enum-class,C++,Enums,C++11,Enum Class,通常,您可以使用以下语法为类定义强制转换: class Test { public: explicit operator bool() { return false; } }; 有没有办法做这个或者类似于枚举类< /C> >?/p> < p>不能在C++中定义非成员的CAST运算符。当然,您不能为枚举定义成员函数。 因此,我建议您使用自由函数将枚举转换为其他类型,与实现强制转换运算符的方法相同 e、 g 有一种很好的方法可以将这些枚举与bool关联,您必须将其拆分为两个文件.h和.cpp

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

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

有没有办法做这个或者类似于<代码>枚举类< /C> >?/p> < p>不能在C++中定义非成员的CAST运算符。当然,您不能为枚举定义成员函数。 因此,我建议您使用自由函数将枚举转换为其他类型,与实现强制转换运算符的方法相同

e、 g


有一种很好的方法可以将这些枚举与bool关联,您必须将其拆分为两个文件.h和.cpp。 如果有帮助的话,这里就是:

枚举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
我没有编译它,所以如果它有任何错误,请放心:)。

不,它不是

实际上,
enum类
根本不是类。之所以使用
class
关键字,是因为突然将非作用域
enum
更改为作用域
enum
将意味着重新处理所有enum代码。所以委员会决定,要区分新旧样式,新的标签会被标记为<代码>类< /代码>,因为它是一个关键字,所以没有代码< EnUM>代码>可以在C++中被命名为代码>类< /代码>。他们本可以选择另一个,但无论如何也没有多大意义


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

否,但可以使用
constexpr
成员和构造函数使普通类类型像枚举类一样工作。然后,您可以添加所有需要的附加成员函数


证明即使使用
开关也可以工作的证据:

#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;
    }
}

如果您这样做了,那么使用
enum类
有什么意义呢<代码>枚举
可以在给定基础类型的情况下进行前向声明,并且作用域为枚举名称。如果您可以自由地将它们从/转换为整数。。。为什么要使用
enum类
?因为它是新的?因为我仍然不想让
enum类
转换为整数,但我可以将它定义为能够转换为
bool
,并使特定值计算为true,其他值计算为false。请注意,没有“隐式强制转换”这样的事情。强制转换是您在源代码中编写的内容。它告诉编译器进行转换。因此,强制转换是一种显式转换。编译器也可以在没有强制转换的情况下进行一些转换;这些被称为“隐式转换”。@NicolBolas我在这里搜索是因为我希望隐式转换为bool,其中一个枚举是SUCCESS,另一个是错误代码。显然,我们可以进行比较,但对于变量名来说,为了清晰起见,不需要这样做。。。一种情况是使用C样式的位字段@Nicolas为逐位操作设置一组标志。对于一个类,例如,
MyCBitfield
,它允许程序员将转换定义为
static\u cast(1)供参考:不能同时拥有这两个。只有一个或另一个。挑剔:
TestToString
应该返回一个
const char*
。挑剔:
TestToString
应该返回
std::string
enum类
最初是由C++/CLI以几乎相同的语义使用的。该标准采用了现有的语法并对其进行了标准化。太糟糕了,C++ + CLI没有使用<代码>枚举名称空间< />代码,Boost是一个很好的例子——查看非C++ 11的部分(<代码> BooStgNosiSnopeDeNeNeS/<代码>),并扩展“你可以使一个普通类类型像EnUM类”——不幸的是,你不能,在C++中,因为C++‘代码>开关是愚蠢的(在保存一些不变量,例如私有构造函数的情况下,也很难/不可能把它变成一个POD)。如果你定义一个转换函数为整数或枚举类型,你可以让你的类<代码>开关>代码>。你所说的“
switch
是愚蠢的”是什么意思?(如果您还记得您试图指出的要点)@KonradRudolph:请注意,值
A
B
Z
,实际上不必存在于秘密枚举类类型中。。。枚举类对象(与传统枚举不同)保证能够存储与其基础类型相同的一组值,无论它们是否是按位或下枚举数闭包的一部分。@BenVoigt我知道您将如何使用它。事实上,CRTP可以与此配合使用。
#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;
    }
}
#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;
}