Generic way to cast int to enum in C++

前端 未结 8 2031
[愿得一人]
[愿得一人] 2020-12-04 11:26

Is there a generic way to cast int to enum in C++?

If int falls in range of an enum it should return

相关标签:
8条回答
  • 2020-12-04 11:54

    What do you think about this one?

    #include <iostream>
    #include <stdexcept>
    #include <set>
    #include <string>
    
    using namespace std;
    
    template<typename T>
    class Enum
    {
    public:
        static void insert(int value)
        {
            _set.insert(value);
        }
    
        static T buildFrom(int value)
        {
            if (_set.find(value) != _set.end()) {
                T retval;
                retval.assign(value);
                return retval;
            }
            throw std::runtime_error("unexpected value");
        }
    
        operator int() const { return _value; }
    
    private:
        void assign(int value)
        {
            _value = value;
        }
    
        int _value;
        static std::set<int> _set;
    };
    
    template<typename T> std::set<int> Enum<T>::_set;
    
    class Apples: public Enum<Apples> {};
    
    class Oranges: public Enum<Oranges> {};
    
    class Proxy
    {
    public:
        Proxy(int value): _value(value) {}
    
        template<typename T>
        operator T()
        {
            T theEnum;
            return theEnum.buildFrom(_value);
        }
    
        int _value;
    };
    
    Proxy convert(int value)
    {
        return Proxy(value);
    }
    
    int main()
    {    
        Apples::insert(4);
        Apples::insert(8);
    
        Apples a = convert(4); // works
        std::cout << a << std::endl; // prints 4
    
        try {
            Apples b = convert(9); // throws    
        }
        catch (std::exception const& e) {
            std::cout << e.what() << std::endl; // prints "unexpected value"
        }
        try {
            Oranges b = convert(4); // also throws  
        }
        catch (std::exception const& e) {
            std::cout << e.what() << std::endl; // prints "unexpected value"
        }
    }
    

    You could then use code I posted here to switch on values.

    0 讨论(0)
  • 2020-12-04 11:54

    C++0x alternative to the "ugly" version, allows for multiple enums. Uses initializer lists rather than switches, a bit cleaner IMO. Unfortunately, this doesn't work around the need to hard-code the enum values.

    #include <cassert>  // assert
    
    namespace  // unnamed namespace
    {
        enum class e1 { value_1 = 1, value_2 = 2 };
        enum class e2 { value_3 = 3, value_4 = 4 };
    
        template <typename T>
        int valid_enum( const int val, const T& vec )
        {
            for ( const auto item : vec )
                if ( static_cast<int>( item ) == val ) return val;
    
            throw std::exception( "invalid enum value!" );  // throw something useful here
        }   // valid_enum
    }   // ns
    
    int main()
    {
        // generate list of valid values
        const auto e1_valid_values = { e1::value_1, e1::value_2 };
        const auto e2_valid_values = { e2::value_3, e2::value_4 };
    
        auto result1 = static_cast<e1>( valid_enum( 1, e1_valid_values ) );
        assert( result1 == e1::value_1 );
    
        auto result2 = static_cast<e2>( valid_enum( 3, e2_valid_values ) );
        assert( result2 == e2::value_3 );
    
        // test throw on invalid value
        try
        {
            auto result3 = static_cast<e1>( valid_enum( 9999999, e1_valid_values ) );
            assert( false );
        }
        catch ( ... )
        {
            assert( true );
        }
    }
    
    0 讨论(0)
提交回复
热议问题