Boost logo

Boost :

Subject: Re: [boost] [enums] Request for comments on an enum-oriented library
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2011-08-21 12:19:06


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

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


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