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 23The `boost/core/scoped_enum.hpp` header contains a number of macros that can be used to generate 24C++11 scoped enums (7.2 \[dcl.enum\]) if the feature is supported by the compiler, otherwise emulate 25it with C++03 constructs. The `BOOST_NO_CXX11_SCOPED_ENUMS` macro from Boost.Config is used to detect 26the feature support in the compiler. 27 28Some 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 38The 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 49These 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 53It 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 64The enumeration supports explicit conversion from the underlying type. 65 66The enumeration can be forward declared: 67 68 BOOST_SCOPED_ENUM_FORWARD_DECLARE(future_errc); 69 70There are however some limitations. The emulated scoped enum is not a C++ enum, so `is_enum< future_errc >` will be `false_type`. 71 72The 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 79use 80 81 switch (boost::native_value(ev)) 82 { 83 case future_errc::broken_promise: 84 // ... 85 86and instead of 87 88 template <> 89 struct is_error_code_enum< future_errc > : 90 public true_type 91 { 92 }; 93 94use 95 96 template <> 97 struct is_error_code_enum< BOOST_SCOPED_ENUM_NATIVE(future_errc) > : 98 public true_type 99 { 100 }; 101 102Explicit 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 106In 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: 107 108 enum enum_regular { REGULAR_A, REGULAR_B }; 109 110 BOOST_SCOPED_ENUM_DECLARE_BEGIN(enum_scoped) 111 { 112 a, b 113 } 114 BOOST_SCOPED_ENUM_DECLARE_END(enum_scoped) 115 116 void regular_or_int(enum_regular); // (1) 117 void regular_or_int(int); // (2) 118 void scoped_or_int(enum_scoped); // (3) 119 void scoped_or_int(int); // (4) 120 121 regular_or_int(REGULAR_A); // calls (1) in C++03 and C++11 122 scoped_or_int(enum_scoped::a); // calls (3) in C++11 but (4) in C++03! 123 scoped_or_int(enum_scoped(enum_scoped::a)); // calls (3) in C++03 and C++11 124 125Here is usage example: 126 127 BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(algae, char) 128 { 129 green, 130 red, 131 cyan 132 } 133 BOOST_SCOPED_ENUM_DECLARE_END(algae) 134 ... 135 algae sample( algae::red ); 136 void foo( algae color ); 137 ... 138 sample = algae::green; 139 foo( algae::cyan ); 140 141[endsect] 142 143[section Deprecated syntax] 144 145In early versions of the header there were two ways to declare scoped enums, with different pros and cons to each. 146The other way used a different set of macros: 147 148 BOOST_SCOPED_ENUM_START(algae) 149 { 150 green, 151 red, 152 cyan 153 }; 154 BOOST_SCOPED_ENUM_END 155 ... 156 BOOST_SCOPED_ENUM(algae) sample( algae::red ); 157 void foo( BOOST_SCOPED_ENUM(algae) color ); 158 ... 159 sample = algae::green; 160 foo( algae::cyan ); 161 162Here `BOOST_SCOPED_ENUM_START` corresponds to `BOOST_SCOPED_ENUM_DECLARE_BEGIN`, `BOOST_SCOPED_ENUM_END` to `BOOST_SCOPED_ENUM_DECLARE_END` 163and `BOOST_SCOPED_ENUM` to `BOOST_SCOPED_ENUM_NATIVE`. Note also the semicolon before `BOOST_SCOPED_ENUM_END`. 164 165In the current version these macros produce equivalent result to the ones described above and are considered deprecated. 166 167[endsect] 168 169[section Acquiring the underlying type of the enum] 170 171The header `boost/core/underlying_type.hpp` defines the metafunction `boost::underlying_type` which can be used to 172obtain the underlying type of the scoped enum. This metafunction has support for emulated scoped enums declared with 173macros in `boost/core/scoped_enum.hpp`. When native scoped enums are supported by the compiler, this metafunction 174is equivalent to `std::underlying_type`. 175 176Unfortunately, there are configurations which implement scoped enums but not `std::underlying_type`. In this case 177`boost::underlying_type` has to be specialized by user. The macro `BOOST_NO_UNDERLYING_TYPE` is defined to indicate 178such cases. 179 180[endsect] 181 182[section Acknowledgments] 183 184This scoped enum emulation was developed by Beman Dawes, Vicente J. Botet Escriba and Anthony Williams. 185 186Helpful comments and suggestions were also made by Kjell Elster, Phil Endecott, Joel Falcou, Mathias Gaunard, Felipe Magno de Almeida, 187Matt Calabrese, Daniel James and Andrey Semashev. 188 189[endsect] 190 191[endsect] 192