Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

scoped_enum

Overview
Deprecated syntax
Acquiring the underlying type of the enum
Acknowledgments

Authors

  • Beman Dawes
  • Vicente J. Botet Escriba
  • Anthony Williams

The boost/core/scoped_enum.hpp header contains a number of macros that can be used to generate C++11 scoped enums (7.2 [dcl.enum]) if the feature is supported by the compiler, otherwise emulate it with C++03 constructs. The BOOST_NO_CXX11_SCOPED_ENUMS macro from Boost.Config is used to detect the feature support in the compiler.

Some of the enumerations defined in the standard library are scoped enums.

enum class future_errc
{
    broken_promise,
    future_already_retrieved,
    promise_already_satisfied,
    no_state
};

The user can portably declare such enumeration as follows:

BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
{
    broken_promise,
    future_already_retrieved,
    promise_already_satisfied,
    no_state
}
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)

These macros allows to use future_errc in almost all the cases as an scoped enum.

future_errc ev = future_errc::no_state;

It is possible to specify the underlying type of the enumeration:

BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(future_errc, unsigned int)
{
    broken_promise,
    future_already_retrieved,
    promise_already_satisfied,
    no_state
}
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)

The enumeration supports explicit conversion from the underlying type.

The enumeration can be forward declared:

BOOST_SCOPED_ENUM_FORWARD_DECLARE(future_errc);

There are however some limitations. The emulated scoped enum is not a C++ enum, so is_enum< future_errc > will be false_type.

The emulated scoped enum can not be used in switch nor in template arguments. For these cases the user needs to use some helpers. Instead of

switch (ev)
{
case future_errc::broken_promise:
    // ...

use

switch (boost::native_value(ev))
{
case future_errc::broken_promise:
    // ...

and instead of

template <>
struct is_error_code_enum< future_errc > :
    public true_type
{
};

use

template <>
struct is_error_code_enum< BOOST_SCOPED_ENUM_NATIVE(future_errc) > :
    public true_type
{
};

Explicit conversion to the underlying type should be performed with boost::underlying_cast instead of static_cast:

unsigned int val = boost::underlying_cast< unsigned int >(ev);

In C++03, scoped enums behave differently in case of calling an overloaded function when one overload takes a scoped enum as a parameter, and the other takes a parameter of an integral type. Consider the following code:

enum enum_regular { REGULAR_A, REGULAR_B };

BOOST_SCOPED_ENUM_DECLARE_BEGIN(enum_scoped)
{
    a, b
}
BOOST_SCOPED_ENUM_DECLARE_END(enum_scoped)

void regular_or_int(enum_regular); // (1)
void regular_or_int(int);          // (2)
void scoped_or_int(enum_scoped);   // (3)
void scoped_or_int(int);           // (4)

regular_or_int(REGULAR_A);                  // calls (1) in C++03 and C++11
scoped_or_int(enum_scoped::a);              // calls (3) in C++11 but (4) in C++03!
scoped_or_int(enum_scoped(enum_scoped::a)); // calls (3) in C++03 and C++11

Here is usage example:

BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(algae, char)
{
    green,
    red,
    cyan
}
BOOST_SCOPED_ENUM_DECLARE_END(algae)
...
algae sample( algae::red );
void foo( algae color );
...
sample = algae::green;
foo( algae::cyan );

In early versions of the header there were two ways to declare scoped enums, with different pros and cons to each. The other way used a different set of macros:

BOOST_SCOPED_ENUM_START(algae)
{
    green,
    red,
    cyan
};
BOOST_SCOPED_ENUM_END
...
BOOST_SCOPED_ENUM(algae) sample( algae::red );
void foo( BOOST_SCOPED_ENUM(algae) color );
...
sample = algae::green;
foo( algae::cyan );

Here BOOST_SCOPED_ENUM_START corresponds to BOOST_SCOPED_ENUM_DECLARE_BEGIN, BOOST_SCOPED_ENUM_END to BOOST_SCOPED_ENUM_DECLARE_END and BOOST_SCOPED_ENUM to BOOST_SCOPED_ENUM_NATIVE. Note also the semicolon before BOOST_SCOPED_ENUM_END.

In the current version these macros produce equivalent result to the ones described above and are considered deprecated.

The header boost/core/underlying_type.hpp defines the metafunction boost::underlying_type which can be used to obtain the underlying type of the scoped enum. This metafunction has support for emulated scoped enums declared with macros in boost/core/scoped_enum.hpp. When native scoped enums are supported by the compiler, this metafunction is equivalent to std::underlying_type.

Unfortunately, there are configurations which implement scoped enums but not std::underlying_type. In this case boost::underlying_type has to be specialized by user. The macro BOOST_NO_UNDERLYING_TYPE is defined to indicate such cases.

This scoped enum emulation was developed by Beman Dawes, Vicente J. Botet Escriba and Anthony Williams.

Helpful comments and suggestions were also made by Kjell Elster, Phil Endecott, Joel Falcou, Mathias Gaunard, Felipe Magno de Almeida, Matt Calabrese, Daniel James and Andrey Semashev.


PrevUpHomeNext