| [/ |
| / Copyright (c) 2009 Beman Dawes |
| / Copyright (c) 2011-2012 Vicente J. Botet Escriba |
| / Copyright (c) 2012 Anthony Williams |
| / Copyright (c) 2014 Andrey Semashev |
| / |
| / Distributed under the Boost Software License, Version 1.0. (See accompanying |
| / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| /] |
| |
| [section:scoped_enum scoped_enum] |
| |
| [simplesect Authors] |
| |
| * Beman Dawes |
| * Vicente J. Botet Escriba |
| * Anthony Williams |
| |
| [endsimplesect] |
| |
| [section Overview] |
| |
| 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. First, the emulated scoped enum is not a C++ enum, so `is_enum< future_errc >` will be `false_type`. |
| |
| Second, 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 |
| { |
| }; |
| |
| Lastly, 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); |
| |
| 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 ); |
| |
| [endsect] |
| |
| [section Deprecated syntax] |
| |
| 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. |
| |
| [endsect] |
| |
| [section Acquiring the underlying type of the enum] |
| |
| 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. |
| |
| [endsect] |
| |
| [section Acknowledgments] |
| |
| 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. |
| |
| [endsect] |
| |
| [endsect] |