|
Boost : |
Subject: [boost] [enums] Request for comments on an enum-oriented library
From: Beren Minor (beren.minor+boost_at_[hidden])
Date: 2011-08-11 16:46:21
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. 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.
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".
- 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).
- 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.
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 genereal 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.
- 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.
- 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).
- I don't have any other environment available except from my Debian
Linux box, so I couldn't test on anything else than gcc. I don't really
expect it to work with anything else. Actually, my main build scripts
themselves are probably broken on anything else than my computer. [1]
That said, if anyone wants to take a look at it and share his thoughts, the
library can be found here : https://github.com/berenm/libtenum
Best regards,
Beren Minor
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.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk