
Le 15/08/11 14:54, Beren Minor a écrit :
Thanks for your comments Vincente, I'll try to answer to some points.
I don't know if you know my development of Boost.Enums on the sandbox (https://svn.boost.org/svn/boost/sandbox/enums/libs/enums/doc/html/index.html). Were you aware of it? Yes, as I said, I know that there already are some enum libraries in development at Boost. I didn't know exactly how stable and how active was the development though. My point wasn't to offer another one but to get some comments on my code and on the design choices I took. I wanted to be sure you were aware of it. See my comments below about some design choices you have taken. I've had a quick look at yours, but there were some point refraining me from using it, like stream I/O, no integer implicit conversion. Stream I/O can be added to the library. Boost.Enums provides implicit conversion to integers with BOOST_ENUM_TYPE_... macros.
The library is not stable enough and doesn't takes care of stream I/O yet. Output to a stream is quite simple to add as the library provides enum to string conversion. Input from a stream will be a little more complex in the general case, but quite simple if the associated string doesn't contains white characters. I'm not sure the stream I/O of enums shouldn't use directly the string form. A manipulator could be used to this respect. I need to think about it a little more. Stream I/O was a very important requirement to me. Initially, I've coded the library to help me reading and writing key mappings from and to a configuration file. The keys were represented by enums, and could be modified with a bit field combination of modifier keys (alt, ctrl, shift...). I did want to have a straightforward conversion from string representation to enum representation. Additionally, when logging enum values, I wanted to have the enum value printed out instead of a obscure integer value. I understand the needs. There is a drawback that I've forgotten in my initial mail, my library doesn't support white space in enum values either. As you say, it's much more simpler like this, and seemed an acceptable constraint to me. Right. IIUC this is an enum that can take only the enum literals, isn't it? If yes, I suggest an alternative name: strong_enum.
Note: My library doesn't provide strong enums. The names are probably a little bit a matter of taste (although strong enum is maybe better than static), but yes, restricting values to explicitly defined literals is the purpose of this flavor. OK. I will add this kind of enums to the list of possible enhancements of my library. IIUC this is a classical enum that allow to store other values than the enum literals. I suggest to call them just enum. The specificity is associated to I/O on streams. I guess that this feature could be orthogonal to the class. Also right, but I dont think that reusing the name enum is a good idea, it can be confusing with the native one, Boost.Enums defines enum_class (no implicit conversion) and enum_type (implicit conversion) which follow the semantics of C++0x scoped enums. With this names there is no possible confussion.
and "dynamic enums" are not just enums. The allowed values are in a given range, where plain enums can have any value. The specificity is associated with stream I/O, as for "static enums", as in memory, the enum variable can still take any value as the variable isn't anything more than the plain old enum itself. This is maybe not a good idea, and maybe operations should return the "unknown" value, even in-memory, if the given value is not one of the allowed ones. Why do you need to constraint the values of the dynamic enums to a range?
Additionally, when using C++11, the dynamic enums also add +,-,+= and -= operators between enum and integers, that returns an enum value. "Static enums" do only define operators between integer and enums (integer at the left hand side), that works like integer operation and automatically casts the enum value to integer. I'm not sure if it is a good idea to have the operator change its meaning whether the enum is on the lhs or rhs though...
- No namespace support.
I guess this is what the standard call scoped enums, isn't it? My library provides an emulation of scoped enums with some limitations. Some syntactic workarounds need to be used to overcome the limitations. Scoped enums is what is used for all the flavors. In C++98, the enum is wrapped in a struct, and typedefed at namespace scope to emulate scoped enums, in C++11 enum class are used. There is no way to add enum values to namespace scope, but that was intentional and part of my requirements. What I mean here, is that the enum has to be declared in the global namespace because the macros expands to some template specialization code that will generate an error if not in the same namespace as the template declaration. To enable in-namespace enums here, I would need to know the current namespace, close it, then declare the specializations, and reopen it after. I don't think to be able to do so yet. The other way is not to have template specialization of a template that is not in the same namespace... I understand the issue now. Boost.Enums has the same problem. The syntax associated to this example
lte_enum(static_enum, lte_ev(value1,2) lte_e(value2) lte_en(value3,"value_number_3"), ::boost::uint8_t ) This is the syntax when using "shortcut" macros, which isn't enabled by default. As in the test files, I've added this functionality to have much shorter macros for the definition, but the names are much less explicit and I think it may be good for writing lighter code, but not good for comprehension. What's more understandable between "lte_en" and "TENUM_ELEMENT_NAMED"?
BOOST_ENUM_TYPE(static_enum,::boost::uint8_t, ( (value1) (2) ) ( (value2) ) ( (value3) () ("value_number_3") )
I don't know if this is more readable to you. I don't like the overcrowding of parentheses, but that's my personal taste. We aren't doing LISP here, are we? :-) No we are not doing Lisp, but macro preprocessing (provided by C/C++). Boost.Local and Boost.Contract has find a way to use some specific symbols to mean specific things. Maybe you could use the default to mean
I don't think it is a good idea to provide these operators. Enums are created explicitly from integer literals. Having the possibility to create them implicitly when doing arithmetic operations seems counter-intuitive. Boost.Enums provide a framework to define ordinal enums. With ordinal enums, you can get the position of an enum respect to the enumeration literals, and get the value associated to a position. Maybe this can respond to this need. You can also see an enum as a range, and then it has a sens to use iterators operators on the associated iterator. the next defaulted value. lte_evn(value3,default,"value_number_3"),
I was looking for the Jamfile to run the test. I see now that there is a Jamroot file on the root. It would be better to provide a Jamfile for the test directory as the other Boost libraries do. I will try to run it. The library is meant to be build separately from boost tree. The Jamroot is used as the main build file, and running bjam from the library folder should do the trick (I don't know how this works on windows though...).
Oh, I see. Best, Vicente