123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- [/
- / 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. 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 );
- [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]
|