Boost logo

Boost :

Subject: Re: [boost] [enums] Request for comments on an enum-oriented library
From: Vicente Botet (vicente.botet_at_[hidden])
Date: 2011-08-15 04:51:08


Beren Minor wrote:
>
> Hi all,
>
> I'm currently writing a C++ library to add some functionalities to enums,
> and am looking for comments and feedbacks. Boost is a reference, and I
> would
> be glad if some C++ expert here could take a moment to look at what I've
> written and tell me his thoughts.
>
> I know that there was already some discussions about enums here, and some
> early implementations of enum libraries at Boost, but I couldn't find any
> that fitted my requirements, or any that was in an stable enough stage.
>

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?

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.
  

> My
> goal wasn't to submit another one to Boost (although I would be really
> proud
> of it, I'm not thinking about it yet, just looking for comments), but to
> implement something usable for some of my specific needs. Initially I was
> only looking for enum (de)serialization, however I think that these needs
> can be quite common, and that the library could be used by others as well.
> That's why I'm trying to find some comments and to share my work.
>

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.
 

> My goal was to implement a library following these requirements :
>
> - Extend the enum concept with different flavors.
> - Scope the enum constants out of namespace scope.
> - Do not get rid of implicit integer cast, or at least, try to provide
> enum/integer interoperability so we don't have to cast all the time.
> - No overhead, keep the enum constants as light as they are natively.
>
> For the first requirement, I wanted to add three new flavors to enums,
> that
> I've called "static enums", "dynamic enums" and "bit fields". The main
> difference between them is the way these enums are (de)serialized and the
> available enum / enum and enum / integer operators when this is meaningful
> (only when using C++0x, with scoped enums).
>
> - Static enums only allow explicitly defined constants (with specified
> or
> implicit integer values), any other value will result in a
> (de)serialization
> to special value "unknown".
>

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.

> - Dynamic enums allow explicitly defined constants and offsets from
> these constants, within a given global range (from the first constant
> to the
> specified upper integer limit).
> Every value within the range will be serializable, any other will
> result
> in "unknown". An integer value between two enum constants will be
> (de)serialized as the nearest lower enum constant plus an offset.
> For example, if the enum is defined as { value1 = 1, value2 = 5...,
> unknown = 10 }, the available range would be from 1 to 9, and the
> integer 4
> will be serialized as "value1#3" which means (value1 + 3).
>

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.

> - Bit fields enums only allow combination of explicitely defined
> constants.
> These will be (de)serialized as a combination of every defined enum
> constants, any other value will be (de)serialized as "unknown". This
> flavor
> restricts constants values to bitwise distinct integers, and to values
> different from 0 in order to be able to decompose the enum into the
> specified enum constants. 0 being the special "unknown" value for this
> flavor.
> For example, for an enum defined as { bit1 = 0b001, bit2 = 0b010, bit3
> =
> 0b100... }, an instance of this enum with an integer value of 3 will be
> serialized as "bit1+bit2", and "bit1+bit3" will be deserialized as an
> enum
> instance of integer value 5.
>

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

> As I said, the library obviously uses Boost, and in an extensive way Boost
> Preprocessor macros, and tries to integrate nicely with Boost libraries.
> Serialization, for example, is done through stream template operators, and
> should be usable with the Boost Lexical Cast library.
> These isn't any real documentation yet, except from doxygen (although not
> yet complete, I've tried to be verbose), but I think that the library is
> simple enough to be understood by reading the source code, and I've got
> some
> unit tests to help getting the general idea.
>
> Lastly, I still have some issues about some points, mostly because of the
> use of macros and boilerplate code, but I hope to be able to fix them.
>
> - 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.

> - Enum declaration comes with the serialization code. I would like to
> be
> able to separate definition and declaration of this code, but I'm not
> sure
> how to do that properly without overhead for the developer. I'll have
> to
> think about it.
>

I see two options. Either the library provide two set of macros, with and
without serialization, or the library is able to generate the serialization
code from some static information provided by the basic macros. I will see
how this can be done with Boost.Enums.

> - The writing overhead of the enum declaration (compared to plain old
> enum) is still a little bit too much for my taste, but I don't know if
> I'll
> be able to do much better without introducing some obscure and
> meaningless
> helper macros.
> This is mainly because of the need of declaring the enum constants in a
> Boost Preprocessor sequence, in order to be able to use it at various
> places
> to generate the enum declaration as well as the serialization code.
> - Also, the declaration could be cleaner if I could find a way to
> implement optional parameters in macros, but that seems like difficult
> to do
> (or I haven't found out yet how to do).
>

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
)

is with my library something like

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.

On compiler providing variadic macros I expect to be able to provide also
this alternative

BOOST_ENUM_TYPE(static_enum,::boost::uint8_t,
    (value1) (2),
    value2,
    (value3) () ("value_number_3")
)

Note the use of () to denote the default value for the 3rd literal.

>
> Notes:
> [1] I've added a "portable-build" branch to my git repo if anyone want to
> try running the tests cases somewhere else. Build is done with bjam.
>
>

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.

Best,
Vicente

--
View this message in context: http://boost.2283326.n4.nabble.com/enums-Request-for-comments-on-an-enum-oriented-library-tp3737312p3744170.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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