Is it possible to manually define a conversion for an enum class?

前端 未结 3 2176
自闭症患者
自闭症患者 2020-12-30 18:37

Normally you can define a cast for a class by using the following syntax:

class Test {
public:
  explicit operator bool() { return false; }
};
相关标签:
3条回答
  • 2020-12-30 19:08

    You cant define non-member cast operators in C++. And you certainly cant define member functions for enums. So I suggest you do free functions to convert your enum to other types, the same way you would implement cast operators.

    e.g.

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

    There is a nice way of associating those enums to bools, you have to split it on two files .h and .cpp. Here it is if it helps:

    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
    

    I didnt compile it so take it easy if it has any errors :).

    0 讨论(0)
  • 2020-12-30 19:11

    No, but you can make a normal class type act like an enum class, using constexpr members and constructors. And then you can add all the additional member functions you want.


    Proof that it can work even with 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;
        }
    }
    

    Proof that working with switch does not require implicit interconversion with 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;
    }
    
    0 讨论(0)
  • 2020-12-30 19:30

    No, it's not.

    Actually, an enum class is no class at all. The class keyword is only used because suddenly changing the unscoped enum to a scoped enum would have mean reworking all enums codes. So the committee decided that to distinguish between new-style and old-style enums, the new ones would be tagged with class, because it's a keyword already so no enum could have been named class in C++. They could have picked another, it would not have made much more sense anyway.

    However, despite the class keyword they are still regular enums in that only enumerators (and potentially values assigned to them) are allowed within the brackets.

    0 讨论(0)
提交回复
热议问题