51

通常、次の構文を使用してクラスのキャストを定義できます。

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

これを行う方法や、に似た方法はありenum classますか?

4

3 に答える 3

26

いいえ、ちがいます。

実際、 anenum classはまったくクラスではありません。キーワードが使用されるのは、スコープ外をclass突然enumスコープ付きに変更すると、すべての列挙型コードenumを作り直すことになるからです。そのため、委員会は、新しいスタイルの列挙型と古いスタイルの列挙型を区別するために、新しいスタイルの enum を でタグ付けすることを決定しました。彼らは別のものを選ぶことができたかもしれませんが、とにかくそれ以上の意味はありませんでした.classenumclass

ただし、classキーワードにもかかわらず、列挙子 (およびそれらに割り当てられる可能性のある値) のみが括弧内で許可されるという点で、それらは依然として通常の列挙型です。

于 2012-10-05T20:37:29.483 に答える
18

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;
}
于 2012-10-05T22:03:40.050 に答える
4

C++ で非メンバー キャスト演算子を定義することはできません。また、列挙型のメンバー関数を定義することはできません。したがって、キャスト演算子を実装するのと同じ方法で、列挙型を他の型に変換する関数を解放することをお勧めします。

例えば

bool TestToBool(enum_e val)
{
    return false;
}

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

これらの列挙型を bool に関連付ける良い方法があります。それを .h と .cpp の 2 つのファイルに分割する必要があります。それが役立つ場合は次のとおりです。

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

私はそれをコンパイルしなかったので、エラーがある場合は簡単にしてください:)。

于 2012-10-05T20:36:25.677 に答える