
From: Maksym Motornyy <mmotorny@yandex.ru>
I think that the names are only "meaningful" if the source language and the application user's language are the same. In general this kind of ability is useful in debugging but in real applications the restraints on identifiers is too limiting (i.e. no punctuation, no accents, no spaces). Far more powerful would be the ability to associate arbitrary data with an enum. This I believe is relatively easy to add to your framework.
Yes, mainly the "meaningful" names can be used for debugging and logging. As I wrote in above reply to Sebastien Martel, arbitary data can be added by means of enumerator-specific methods.
We write real applications, but we don't need i18n support in them as they are for internal use. We have a better enum mechanism, though it relies on macros to generate the necessary code. Though that mechanism, we frequently turn enumerators into strings (in both long and short forms) and turn strings into enumerators.
I wish to state for the record, I believe macros should only be used as a last resort.
Here's our syntax: SA_BEGIN_ENUM(example) enumerator1[ = expression], enumerator2[ = expression], ... enumeratorN[ = expression] SA_END_ENUM(example) The result is, effectively: class example { public: enum value { enumerator1[ = expression], enumerator2[ = expression], ... enumeratorN[ = expression] }; example() { } example(value value_i) : value_(value_i) { } operator value() const { return value_; } std::string to_string(bool verbose_i = false) const { return map_s.get_name(value_, verbose_i); } static example from_string(std::string const & name_i, example not_found_i) { return static_cast<value>(map_s.get_value(name_i, not_found_i)); } static example from_string(std::string const & name_i) // throws an exception { return static_cast<value>(map_s.get_value(name_i)); } static void dump() { map_s.dump(); } // define various operators private: static ::saol::details::enum_name_mapper map_s; value value_; public: static void register_enumerators(); }; template <typename Stream> Stream & operator <<(Stream & stream_io, example value_i) { return stream_io << value_i.to_string(); } To set the names, we use SA_BEGIN_ENUMERATOR_REGISTRATION(example) SA_REGISTER_ENUMERATOR(enumerator1, "Some long description") SA_REGISTER_SIMPLE_ENUMERATOR(enumerator1) ... SA_END_ENUMERATOR_REGISTRATION(example) SA_REGISTER_ENUMERATOR registers the enumerator name converted to a string (preprocessor stringizing) plus the long description as the non-verbose and verbose forms, respectively. SA_REGISTER_SIMPLE_ENUMERATOR registers the enumerator name as both the long and short forms.
Absolutely agree. If you find "meaningful" names not very useful feature, enumerator definition can be done without macros.
We use that regularly. Since the macros generate typesafe code, we don't find their use problematic. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;