Symbolic enums

By default, enums are treated as though they are integers. This works well for serialisation, but if the data is meant to be read by a human, it is desirable to display the enums in symbolic form.

In order to do this, classdesc will emit descriptors using Enum_handle<E>, where E is an enum, which wraps an enum variable. In particular, the Enum_handle will return a string symbolic representation of the enum, or assign the appropriate value to the enum variable when assigned a string constant representing the symbolic value of the enum:

  template <class T> //T is an enum
  class Enum_handle
  {
  public:
    Enum_handle(T& arg); // wrap enum arg
    operator std::string() const; //symbolic form of enum
    operator int() const; //integral value of the enum
    const Enum_handle& operator=(T x);
    const Enum_handle& operator=(int x);
    const Enum_handle& operator=(const std::string& x); //symbolic assignment  
  };
Classdesc handles writing the dictionaries needed to perform this conversion to and from symbolic constants. See the xml_pack descriptor for an example of its use.

Access to the enum reflection data is via the EnumKeys class

  template <class T>
  class EnumKeys
  {
  public:
    int operator()(std::string key);
    std::string operator()(int val);
    size_t size() const;
    iterator begin() const;
    iterator end() const;
    Siterator sbegin() const {return begin();}
    Siterator send() const {return end();}
    Viterator vbegin() const {return begin();}
    Viterator vend() const {return end();}
  };

template <class T> const EnumKeys<T>& enum_keys();
So enum_keys<enum Foo>()("bar") returns the numerical value of the enum constant bar and enum_keys<enum Foo>()(bar) returns the string value "bar".

The various iterators allow iteration, or population of containers:

const EnumKeys<Foo> e(enum_keys<Foo>());
map<Foo,string> m(e.begin(), e.end());
vector<string> s(e.sbegin(), e.send());
vector<Foo> v(e.vbegin(), e.vend());
for (auto i: enum_keys<Foo>()) cout << i.second <<"="<<i.first<< endl;