Boost logo

Boost :

Subject: Re: [boost] [enums] Request for comments on an enum-oriented library
From: Beren Minor (beren.minor+boost_at_[hidden])
Date: 2011-08-15 08:54:03


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'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.

> 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.
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.

> I'm not sure the word serialization is the most appropriated in your case,
> as what you provide is stream I/O. Anyway the library should provide also
> serialization as defined in Boost.Serialization. I will add this to my to do
> list.

I'll have a look at what's needed for Boost.Serialization.

> 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.

> 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, 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.

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...

> In my library this type should correspond to an enum_set, which offer a safe
> interface for ordinal enums.

Ok, if enum_set is the name you're using to represent a bit field -
where enum literal represent a bit position, this is it.

> > - 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...

> 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? :-)

> 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...).

Best regards,
Beren


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk