Brian Silverman | 407d3cd | 2018-08-04 17:48:52 -0700 | [diff] [blame^] | 1 | [/ |
| 2 | / Copyright (c) 2009 Beman Dawes |
| 3 | / Copyright (c) 2011-2012 Vicente J. Botet Escriba |
| 4 | / Copyright (c) 2012 Anthony Williams |
| 5 | / Copyright (c) 2014 Andrey Semashev |
| 6 | / |
| 7 | / Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 8 | / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 9 | /] |
| 10 | |
| 11 | [section:scoped_enum scoped_enum] |
| 12 | |
| 13 | [simplesect Authors] |
| 14 | |
| 15 | * Beman Dawes |
| 16 | * Vicente J. Botet Escriba |
| 17 | * Anthony Williams |
| 18 | |
| 19 | [endsimplesect] |
| 20 | |
| 21 | [section Overview] |
| 22 | |
| 23 | The `boost/core/scoped_enum.hpp` header contains a number of macros that can be used to generate |
| 24 | C++11 scoped enums (7.2 \[dcl.enum\]) if the feature is supported by the compiler, otherwise emulate |
| 25 | it with C++03 constructs. The `BOOST_NO_CXX11_SCOPED_ENUMS` macro from Boost.Config is used to detect |
| 26 | the feature support in the compiler. |
| 27 | |
| 28 | Some of the enumerations defined in the standard library are scoped enums. |
| 29 | |
| 30 | enum class future_errc |
| 31 | { |
| 32 | broken_promise, |
| 33 | future_already_retrieved, |
| 34 | promise_already_satisfied, |
| 35 | no_state |
| 36 | }; |
| 37 | |
| 38 | The user can portably declare such enumeration as follows: |
| 39 | |
| 40 | BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) |
| 41 | { |
| 42 | broken_promise, |
| 43 | future_already_retrieved, |
| 44 | promise_already_satisfied, |
| 45 | no_state |
| 46 | } |
| 47 | BOOST_SCOPED_ENUM_DECLARE_END(future_errc) |
| 48 | |
| 49 | These macros allows to use `future_errc` in almost all the cases as an scoped enum. |
| 50 | |
| 51 | future_errc ev = future_errc::no_state; |
| 52 | |
| 53 | It is possible to specify the underlying type of the enumeration: |
| 54 | |
| 55 | BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(future_errc, unsigned int) |
| 56 | { |
| 57 | broken_promise, |
| 58 | future_already_retrieved, |
| 59 | promise_already_satisfied, |
| 60 | no_state |
| 61 | } |
| 62 | BOOST_SCOPED_ENUM_DECLARE_END(future_errc) |
| 63 | |
| 64 | The enumeration supports explicit conversion from the underlying type. |
| 65 | |
| 66 | The enumeration can be forward declared: |
| 67 | |
| 68 | BOOST_SCOPED_ENUM_FORWARD_DECLARE(future_errc); |
| 69 | |
| 70 | There are however some limitations. First, the emulated scoped enum is not a C++ enum, so `is_enum< future_errc >` will be `false_type`. |
| 71 | |
| 72 | 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 |
| 73 | |
| 74 | switch (ev) |
| 75 | { |
| 76 | case future_errc::broken_promise: |
| 77 | // ... |
| 78 | |
| 79 | use |
| 80 | |
| 81 | switch (boost::native_value(ev)) |
| 82 | { |
| 83 | case future_errc::broken_promise: |
| 84 | // ... |
| 85 | |
| 86 | and instead of |
| 87 | |
| 88 | template <> |
| 89 | struct is_error_code_enum< future_errc > : |
| 90 | public true_type |
| 91 | { |
| 92 | }; |
| 93 | |
| 94 | use |
| 95 | |
| 96 | template <> |
| 97 | struct is_error_code_enum< BOOST_SCOPED_ENUM_NATIVE(future_errc) > : |
| 98 | public true_type |
| 99 | { |
| 100 | }; |
| 101 | |
| 102 | Lastly, explicit conversion to the underlying type should be performed with `boost::underlying_cast` instead of `static_cast`: |
| 103 | |
| 104 | unsigned int val = boost::underlying_cast< unsigned int >(ev); |
| 105 | |
| 106 | Here is usage example: |
| 107 | |
| 108 | BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(algae, char) |
| 109 | { |
| 110 | green, |
| 111 | red, |
| 112 | cyan |
| 113 | } |
| 114 | BOOST_SCOPED_ENUM_DECLARE_END(algae) |
| 115 | ... |
| 116 | algae sample( algae::red ); |
| 117 | void foo( algae color ); |
| 118 | ... |
| 119 | sample = algae::green; |
| 120 | foo( algae::cyan ); |
| 121 | |
| 122 | [endsect] |
| 123 | |
| 124 | [section Deprecated syntax] |
| 125 | |
| 126 | In early versions of the header there were two ways to declare scoped enums, with different pros and cons to each. |
| 127 | The other way used a different set of macros: |
| 128 | |
| 129 | BOOST_SCOPED_ENUM_START(algae) |
| 130 | { |
| 131 | green, |
| 132 | red, |
| 133 | cyan |
| 134 | }; |
| 135 | BOOST_SCOPED_ENUM_END |
| 136 | ... |
| 137 | BOOST_SCOPED_ENUM(algae) sample( algae::red ); |
| 138 | void foo( BOOST_SCOPED_ENUM(algae) color ); |
| 139 | ... |
| 140 | sample = algae::green; |
| 141 | foo( algae::cyan ); |
| 142 | |
| 143 | Here `BOOST_SCOPED_ENUM_START` corresponds to `BOOST_SCOPED_ENUM_DECLARE_BEGIN`, `BOOST_SCOPED_ENUM_END` to `BOOST_SCOPED_ENUM_DECLARE_END` |
| 144 | and `BOOST_SCOPED_ENUM` to `BOOST_SCOPED_ENUM_NATIVE`. Note also the semicolon before `BOOST_SCOPED_ENUM_END`. |
| 145 | |
| 146 | In the current version these macros produce equivalent result to the ones described above and are considered deprecated. |
| 147 | |
| 148 | [endsect] |
| 149 | |
| 150 | [section Acquiring the underlying type of the enum] |
| 151 | |
| 152 | The header `boost/core/underlying_type.hpp` defines the metafunction `boost::underlying_type` which can be used to |
| 153 | obtain the underlying type of the scoped enum. This metafunction has support for emulated scoped enums declared with |
| 154 | macros in `boost/core/scoped_enum.hpp`. When native scoped enums are supported by the compiler, this metafunction |
| 155 | is equivalent to `std::underlying_type`. |
| 156 | |
| 157 | Unfortunately, there are configurations which implement scoped enums but not `std::underlying_type`. In this case |
| 158 | `boost::underlying_type` has to be specialized by user. The macro `BOOST_NO_UNDERLYING_TYPE` is defined to indicate |
| 159 | such cases. |
| 160 | |
| 161 | [endsect] |
| 162 | |
| 163 | [section Acknowledgments] |
| 164 | |
| 165 | This scoped enum emulation was developed by Beman Dawes, Vicente J. Botet Escriba and Anthony Williams. |
| 166 | |
| 167 | Helpful comments and suggestions were also made by Kjell Elster, Phil Endecott, Joel Falcou, Mathias Gaunard, Felipe Magno de Almeida, |
| 168 | Matt Calabrese, Daniel James and Andrey Semashev. |
| 169 | |
| 170 | [endsect] |
| 171 | |
| 172 | [endsect] |