Boost logo

Boost :

Subject: Re: [boost] Scoped Enum Emulation
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-01-25 16:28:52


Le 25/01/12 13:26, Stewart, Robert a écrit :
> Vicente J. Botet wrote:
>> Le 24/01/12 22:51, Beman Dawes a écrit :
>>> What do others think? Should
>> /boost/detail/scoped_enum_emulation.hpp
>>> functionality be moved to config?
>>>
>>> Are there any improvements that would make the emulation
>>> better, without turning something simple into something
>>> complex?
>> I'm working with a different emulation which uses classes.
>> For example
>>
>> // enum class cv_status;
>> BOOST_DECLARE_STRONG_ENUM_BEGIN(cv_status)
>> {
>> no_timeout,
>> timeout
>> };
>> BOOST_DECLARE_STRONG_ENUM_END(cv_status)
>>
>> The macros are defined as follows:
>>
>> #ifdef BOOST_NO_SCOPED_ENUMS
>> #define BOOST_DECLARE_STRONG_ENUM_BEGIN(x) \
>> struct x { \
>> enum enum_type
>>
>> #define BOOST_DECLARE_STRONG_ENUM_END(x) \
>> enum_type v_; \
>> inline x() {} \
>> inline x(enum_type v) : v_(v) {} \
>> inline operator int() const {return v_;} \
>> friend inline bool operator ==(x lhs, int rhs) \
>> {return lhs.v_==rhs;} \
>> friend inline bool operator ==(int lhs, x rhs) \
>> {return lhs==rhs.v_;} \
>> friend inline bool operator !=(x lhs, int rhs) \
>> {return lhs.v_!=rhs;} \
>> friend inline bool operator !=(int lhs, x rhs) \
>> {return lhs!=rhs.v_;} \
>> };
>>
>> #define BOOST_STRONG_ENUM_NATIVE(x) x::enum_type
>> #else // BOOST_NO_SCOPED_ENUMS
>> #define BOOST_DECLARE_STRONG_ENUM_BEGIN(x) enum class x
>> #define BOOST_DECLARE_STRONG_ENUM_END(x)
>> #define BOOST_STRONG_ENUM_NATIVE(x) x
>> #endif // BOOST_NO_SCOPED_ENUMS
>>
>> While this is not yet a complete emulation of scoped enums,
>> it has the advantage of that there is no need to use a macro to
>> name the strong type.
> It looks decent, but shouldn't int be a computed type based upon the size and signed-ness of enum_type? Of course, you could also provide macros to specify the underlying type and use that, instead of enum_type, as the type of v_. That would increase compatibility with strongly typed enums in C++11.
The implicit underlying type is int. And yes, another set of macros
could be provided to allow to specify the underlying type.
>
> Why convert implicitly to int rather than to enum_type? You could convert to the computed type I mentioned above, but converting to enum_type would ensure the most appropriate conversions, wouldn't it?
The conversion operator should be explicit and to the underlying type,
which is int. I have to change it to use explicit conversion when the
compiler supports it.
>
> It might also be good to put the semicolon closing the enumerated type definition into the _END macro. That would increase symmetry and more strongly tie the _END macro to the construct:
>
> BOOST_DECLARE_STRONG_ENUM_BEGIN(cv_status)
> {
> no_timeout,
> timeout
> }
> BOOST_DECLARE_STRONG_ENUM_END(cv_status)
Yes, this is better.
>
> It would be nice if the macros would produce strongly typed enums, when available, and devolve to emulation when not.
Have you miss the else part?

#else // BOOST_NO_SCOPED_ENUMS
#define BOOST_DECLARE_STRONG_ENUM_BEGIN(x) enum class x
#define BOOST_DECLARE_STRONG_ENUM_END(x)
#define BOOST_STRONG_ENUM_NATIVE(x) x
#endif // BOOST_NO_SCOPED_ENUMS

>
> It might also prove useful to have a macro to forward declare them: BOOST_FORWARD_DECLARE_STRONG_ENUM(name). That would forward declare a normal class, when emulating, and forward declare the enum class otherwise.
>
>
Yes, this can be useful also.

Next follows the new macros with the sugested improvements

#ifdef BOOST_NO_SCOPED_ENUMS
#define BOOST_DECLARE_STRONG_ENUM_UT_BEGIN(NT, UT) \
   struct NT { \
     typedef UT underlying_type; \
     enum enum_type

#ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS

#define BOOST_DECLARE_STRONG_ENUM_UT_END(NT) \
     ; \
     underlying_type v_; \
     inline NT() {} \
     inline NT(enum_type v) : v_(v) {} \
     inline underlying_type underlying() const {return v_;} \
     inline explicit operator underlying_type() const {return
underlying();} \
   };
#else
#define BOOST_DECLARE_STRONG_ENUM_UT_END(NT) \
     ; \
     underlying_type v_; \
     inline NT() {} \
     inline NT(enum_type v) : v_(v) {} \
     inline underlying_type underlying() const {return v_;} \
     inline operator underlying_type() const {return underlying();} \
   };
#endif

#define BOOST_DECLARE_STRONG_ENUM_BEGIN(NT) \
   BOOST_DECLARE_STRONG_ENUM_UT_BEGIN(NT,int)

#define BOOST_DECLARE_STRONG_ENUM_END(NT) \
   BOOST_DECLARE_STRONG_ENUM_UT_END(NT)

#define BOOST_STRONG_ENUM_NATIVE(NT) NT::enum_type
#define BOOST_FORWARD_DECLARE_STRONG_ENUM(NT) struct NT

#else // BOOST_NO_SCOPED_ENUMS

#define BOOST_DECLARE_STRONG_ENUM_UT_BEGIN(NT,UT) enum class NT:UT
#define BOOST_DECLARE_STRONG_ENUM_UT_END(NT) ;
#define BOOST_DECLARE_STRONG_ENUM_BEGIN(NT) enum class NT
#define BOOST_DECLARE_STRONG_ENUM_END(NT) ;

#define BOOST_STRONG_ENUM_NATIVE(NT) NT
#define BOOST_FORWARD_DECLARE_STRONG_ENUM(NT) enum class NT

#endif // BOOST_NO_SCOPED_ENUMS

Thanks for the suggestions.
Vicente


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