
I wrote some code to perform both compile-time and runtime translation between enums and their corresponding string values. The only direction that isn't possible is string->enum at compile time. Is there any interest in this? You can use it as follows: typedef enum { ValueA1, ValueA2 } EnumA; typedef enum { ValueB1, ValueB2 } EnumB; BEGIN_ENUM_MAP_DECLS() BEGIN_ENUM_MAP(EnumA, a_map) ENUM_MAP(ValueA1) //maps ValueA1 to the string "ValueA1", provides both compile-time and run-time lookups. ENUM_MAP_NAME(ValueA2, "custom name") //maps ValueA2 to the string "custom name", provides both compile-time and run-time lookups END_ENUM_MAP() BEGIN_ENUM_MAP(EnumB, b_map) ENUM_MAP(ValueB1) ENUM_MAP(ValueB2) END_ENUM_MAP() END_ENUM_MAP_DECLS() void foo() { //value -> string, compile time BOOST_STATIC_ASSERT(enum_map<EnumA>::value_lookup[ValueA2] == "custom name"); //value -> string, runtime EnumB some_value = get_enum_b_from_external_source(); std::cout << "some_value = " << enum_map<EnumB>::name_lookup[some_value] << std::endl; //prints either 'some_value = ValueB1', or 'some_value = ValueB2' //string -> value, runtime EnumA value = enum_map<EnumA>::name_lookup["custom name"]; BOOST_ASSERT(value == ValueA2); } One particularly useful application of this that I've found is with regards to boost::program_options. You can provide an overload of boost::program_options::validate that uses boost::enable_if with boost::is_enum thus providing automatic support for entry of friendly names corresponding to enumerations on the command line or in a config file. Obviously there's many other easily identifiable uses as well. However, this is a common enough problem that I wonder if anyone else has already attempted something like this, and if so maybe I can look at their code first, or just scrap mine altogether and reuse something existing. If not, I'm sure there is plenty of room for improvement in mine but if it could fit somewhere in boost (perhaps boost/utility) I'd be willing to submit it and make necessary improvements. Unfortunately I don't think it's technically possible to have a simple syntax, even through preprocessor magic, that requires you to only specify the name of each enumerated value once, and end up providing both a definition of the enumeration as well as the mapping from string<->value, but if someone comes up with a way that would obviously be ideal.

On Wed, Jul 22, 2009 at 12:33 AM, Ross Levine<ross.levine@uky.edu> wrote:
How is this different from using a std::map and boost::assign's map_list_of?
Internally it uses an std::map for the runtime lookup, so in that sense maybe not much. But using an std::map won't allow you to do compile-time enum value->string translation. I was also trying to minimize the number of times you had to refer to a single enum value v, so that for example you didn't have to do 2 separate declarations for a compile-time lookup and a runtime lookup. So if you use map_list_of that will give you a runtime lookup and then I think you'll need to respecify all the values using some other mechanism if you additionally want a compile-time lookup. It might be possible to do compile time string->enum translation as well, I know some work was done on an mpl::string, but admittedly I'm still an mpl novice and I didn't look into it.

This is kind of interesting. I actually made something recently to iterate through all the possible values of an enum at runtime; maybe something like that could be incorporated into this? My code also included a way to retrieve the name of the enum value, though the name was automatically the same as the identifier. --SPCD "Celtic Minstrel"

(Oh, my version did separate declaration from definition, too.) --SPCD "Celtic Minstrel"

I'm very interesting in this problem ,I think it's very hard to implement the string to enum translation at compile time, I have no ideas about it, wish you can work it out. Did you have upload your code ? On Mon, Jul 27, 2009 at 12:34 PM, Celtic Minstrel <celtic.minstrel.ca@ gmail.com> wrote:

Fatih wrote:
It is not difficult, though it requires registering the string against the value in a map during runtime initialization. (We use a library initialization mechanism, called from main(), to trigger such initialization.) I've had code, plus simplifying macros, for years that creates an enumerated type within a class named by the caller so that the enumerators are scoped. As part of that, there is support for enumerator-to-string and string-to-enumerator mapping by virtue of registration calls which can map the enumerator to the stringized form (thanks to the preprocessor) or a supplied long name. (The stringized form is mapped, too, in the latter case.) Enum classes solve the scoping part of my solution, of course. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

My own solution for scoping enums has been to enclose it in a namespace rather than a class, and import the name of the actual enum. The only disadvantage is that the namespace must have a different name than the enum; perhaps your solution is better. Of course, C++0x enum classes beat either option.

Celtic Minstrel wrote:
Putting them in a class allows defining operators on the class type that aren't possible on an enumerated type (|=, ^=, etc.). The member functions can be expressed as namespace scope functions, and the static member that holds the maps, can be expressed as a namespace scope variable. However, a class offers privacy not available with a namespace. Thus, a class permits private member functions and data members to better control manipulations. BTW, my reverse lookup (string-to-enumerator) map is populated on first access. The forward direction is done via the registration calls, but the reverse lookup can be built from the forward mappings. That saves memory for the many cases in which the reverse lookup isn't needed. It could, though I never did it, be triggered specifically at initialization time to avoid the first access overhead. There could be a specific call or some flag to indicate whether to do the reverse lookup initialization on first access or early.
Of course, C++0x enum classes beat either option.
Certainly. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Mon, Jul 27, 2009 at 9:54 AM, Stewart, Robert<Robert.Stewart@sig.com> wrote:
Well that's of course not a compile time solution though if it requires runtime initialization. The approach taken by my solution (which I still haven't uploaded to vault btw) scopes the enums with a namespace, and inside the namespace provides a template specialization for each value in the enum that was specified by one of the MAP_ENUM() macro invocations. For example, given the followign enum definition: typedef enum { Value1, Value2 } Enum1; Then the macro sequence: BEGIN_ENUM_MAP(Enum1, map1) ENUM_MAP(Value1, "this is a test") ENUM_MAP(Value2, "test2") END_ENUM_MAP() would generate the following code: namespace map1 { template<Enum1 e> class lookup {}; template<> class lookup<Value1> { static const char* name; }; const char* lookup<Value1>::name = "this is a test"; template<> class lookup<Value2> { static const char* name; }; const char* lookup<Value2>::name = "test2"; } Now, using code such as the following: std::string test = map1::lookup<Value1>::name; which with optimizations on will generate identical code as doing: std::string test = "test2"; Of course my macros generated additional code as well to create and initialize static runtime lookup maps, but due to the inclusion of everything in every translation unit I agree it's not appropriate in its current form. When I get time to re-think about it perhaps I'll address that issue and then consider uploading it.

Zachary Turner wrote:
Quite right. I didn't notice that Fatih wrote "compile time." User-defined literals might be of use, but then only in C++1x. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

At 10:42 PM -0500 7/21/09, Zachary Turner wrote:
I wrote some code to perform both compile-time and runtime translation between enums and their corresponding string values.
This sounds somewhat similar to a couple of projects in the vault. I haven't looked at either of these in a while, so my recollection might be wrong and they will turn out to be unrelated to what you are doing, but you might want to have a look. http://www.boostpro.com/vault/ enum_rev4.6.zip benum_v1.zip
participants (7)
-
Celtic Minstrel
-
Fatih
-
Kim Barrett
-
Mathias Gaunard
-
Ross Levine
-
Stewart, Robert
-
Zachary Turner