Подтвердить что ты не робот

Можно ли вручную определить преобразование для класса enum?

Обычно вы можете определить бросок для класса, используя следующий синтаксис:

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

Есть ли способ сделать это или что-то подобное для enum class?

4b9b3361

Ответ 1

Нет, это не так.

Собственно, enum class не является классом вообще. Ключевое слово class используется только потому, что внезапное изменение незанятого enum на область enum означало бы переработку всех кодов перечислений. Таким образом, комитет решил, что для различения записей нового стиля и старого стиля новые будут помечены class, потому что это ключевое слово уже, поэтому no enum можно было бы назвать class в С++. Они могли бы выбрать другую, это не имело бы никакого смысла.

Однако, несмотря на ключевое слово class, они все еще являются регулярными перечислениями, поскольку в скобках допускаются только перечисляющие (и потенциально назначенные им значения).

Ответ 2

Нет, но вы можете заставить нормальный тип класса действовать как класс enum, используя члены и конструкторы 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;
}

Ответ 3

Вы не можете определить операторы-литеры, не являющиеся членами, в С++. И вы, конечно, не можете определить функции-члены для перечислений. Поэтому я предлагаю вам делать бесплатные функции для преобразования вашего перечисления в другие типы, так же, как и для операторов трансляции.

например.

bool TestToBool(enum_e val)
{
    return false;
}

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

Есть хороший способ связать эти перечисления с bools, вам нужно разбить его на два файла .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

Я не скомпилировал его, так что не стесняйтесь, если у него есть какие-либо ошибки:).