Boost logo

Boost :

Subject: Re: [boost] Scoped Enum Emulation
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2012-01-26 08:56:48


Vicente J. Botet wrote:
> Le 25/01/12 13:26, Stewart, Robert a écrit :
> > Vicente J. Botet wrote:
>
> > 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.

I hadn't read enough about scoped enumerations before to see that the default type is exactly int, unlike unscoped enumerations.

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

I see that now.

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

Yes, I overlooked that.

> Next follows the new macros with the sugested improvements
>
> #ifdef BOOST_NO_SCOPED_ENUMS

Did you mean the following?

#ifndef BOOST_NO_SCOPED_ENUMS

> #define BOOST_DECLARE_STRONG_ENUM_UT_BEGIN(NT, UT) \

I wonder if preprocessor trickery could detect the difference between (NT) and (NT, UT) thereby permitting one macro to produce the right output regardless of whether the underlying type was given. Doing so might require extra parentheses, which might be perceived as worse than two macros.

> struct NT { \
> typedef UT underlying_type; \
> enum enum_type
>
> #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
>
> #define BOOST_DECLARE_STRONG_ENUM_UT_END(NT) \

Since you're not asking the user to repeat UT, maybe this should just be BOOST_DECLARE_STRONG_ENUM_END. That is, use two different macros to introduce the scoped enumeration (if preprocessor tricks can't reduce that to one), but just use one macro to finalize them.

Also, I think "DEFINE" is better than "DECLARE" because you're generating a definition (which is an implicit declaration). Furthermore, doing so would mean that "FORWARD_DECLARE" could be just "DECLARE", if you like.

> ; \
> underlying_type v_; \
> inline NT() {} \

Why "inline"? The definitions are provided inline, so the keyword adds nothing. ISTR that some compiler -- perhaps a very old one -- complains about such use of the inline keyword.

> inline NT(enum_type v) : v_(v) {} \
> inline underlying_type underlying() const {return v_;} \

I've always preferred naming such functions with an "as_" prefix. In this context, you actually know the name of the underlying type, so you could even do as_##UT, though that wouldn't work right for unsigned int, signed int, etc. Maybe the preprocessor can help, for example, to collapse "unsigned int" to "unsigned" so you could generate "as_unsigned" even when UT is "unsigned int".

> 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

It looks to me as if you could simplify the above since the only difference between the sections, with and without BOOST_NO_EXPLICIT_CONVERSION_OPERATORS defined, is one operator. Thus:

#ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS

# define BOOST_DECLARE_STRONG_ENUM_UT_CONVERSION_OPERATOR \
     inline explicit operator underlying_type() const \
     {return underlying();}

#else

# define BOOST_DECLARE_STRONG_ENUM_UT_CONVERSION_OPERATOR \
     inline operator underlying_type() const \
     {return underlying();}

#endif

#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_;} \
     BOOST_DECLARE_STRONG_ENUM_UT_CONVERSION_OPERATOR
   };

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

NP

One last thought: why "strong"? The standard calls them "scoped enumerations" so why not "SCOPED_ENUM_"?

_____
Rob Stewart robert.stewart_at_[hidden]
Software Engineer using std::disclaimer;
Dev Tools & Components
Susquehanna International Group, LLP http://www.sig.com

________________________________

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.


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