Which Typesafe Enum in C++ Are You Using?

2019-01-03 05:00发布

It is common knowledge that built-in enums in C++ are not typesafe. I was wondering which classes implementing typesafe enums are used out there... I myself use the following "bicycle", but it is somewhat verbose and limited:

typesafeenum.h:

struct TypesafeEnum
{
// Construction:
public:
    TypesafeEnum(): id (next_id++), name("") {}
    TypesafeEnum(const std::string& n): id(next_id++), name(n) {}

// Operations:
public:
    bool operator == (const TypesafeEnum& right) const;
    bool operator != (const TypesafeEnum& right) const;
    bool operator < (const TypesafeEnum& right) const;

    std::string to_string() const { return name; }

// Implementation:
private:
    static int next_id;
    int id;
    std::string name;
};

typesafeenum.cpp:

int TypesafeEnum::next_id = 1;

bool TypesafeEnum::operator== (const TypesafeEnum& right) const 
{ return id == right.id; }

bool TypesafeEnum::operator!= (const TypesafeEnum& right) const 
{ return !operator== (right); }

bool TypesafeEnum::operator< (const TypesafeEnum& right) const  
{ return id < right.id; }

Usage:

class Dialog 
{
 ...
    struct Result: public TypesafeEnum
    {
        static const Result CANCEL("Cancel");
        static const Result OK("Ok");
    };


    Result doModal();
 ...
};

const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;

Addition: I think I should have been more specific about the requirements. I'll try to summarize them:

Priority 1: Setting an enum variable to an invalid value should be impossible (a compile-time error) with no exceptions.

Priority 2: Converting an enum value to/from an int should be possible with a single explicit function/method call.

Priority 3: As compact, elegant and convenient declaration and usage as possible

Priority 4: Converting enum values to and from strings.

Priority 5: (Nice to have) Possibility to iterate over enum values.

11条回答
霸刀☆藐视天下
2楼-- · 2019-01-03 05:30

Not sure if this post is too late, but there's an article on GameDev.net which satisfies all but the 5th point (ability to iterate over enumerators): http://www.gamedev.net/reference/snippets/features/cppstringizing/

The method described by the article allows string conversion support for existing enumerations without changing their code. If you only want support for new enumerations though, I'd go with Boost.Enum (mentioned above).

查看更多
Lonely孤独者°
3楼-- · 2019-01-03 05:31

A nice compromise method is this:

struct Flintstones {
   enum E {
      Fred,
      Barney,
      Wilma
   };
};

Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;

It's not typesafe in the same sense that your version is, but the usage is nicer than standard enums, and you can still take advantage of integer conversion when you need it.

查看更多
家丑人穷心不美
4楼-- · 2019-01-03 05:38

I don't. Way too much overhead for little benefit. Also, being able to caste enumerations to different data types for serialization is a very handy tool. I have never seen an instance where a "Type safe" enumeration would be worth the overhead and complexity where C++ offers a good enough implementation already.

查看更多
你好瞎i
5楼-- · 2019-01-03 05:38

I gave an answer to this here, on a different topic. It's a different style of approach which allows most of the same functionality without requiring modification to the original enum definition (and consequently allowing usage in cases where you don't define the enum). It also allows runtime range checking.

The downside of my approach is that it doesn't programmatically enforce the coupling between the enum and the helper class, so they have to be updated in parallel. It works for me, but YMMV.

查看更多
Lonely孤独者°
6楼-- · 2019-01-03 05:38

I am currently writing my own typesafe enum library at https://bitbucket.org/chopsii/typesafe-enums

I am not the most experienced C++ developer ever, but I am writing this due to the shortcomings of the BOOST vault enums.

Feel free to check it out and use them yourself, but they have some (hopefully minor) usability issues, and are probably not at all cross-platform.

Please contribute if you want to. This is my first open source undertaking.

查看更多
登录 后发表回答