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;