forked from boostorg/core
Added docs for scoped_enum.hpp. Extracted underlying_type to a separate header.
This commit is contained in:
@@ -23,7 +23,7 @@ criteria for inclusion is that the utility component be:
|
||||
|
||||
Currently, the Core library contains:
|
||||
|
||||
[table
|
||||
[table
|
||||
[[Component][Utilities]]
|
||||
[
|
||||
[[link core.addressof addressof]]
|
||||
@@ -68,6 +68,10 @@ Currently, the Core library contains:
|
||||
[ref]
|
||||
[`boost::ref`]
|
||||
]
|
||||
[
|
||||
[[link core.scoped_enum scoped_enum]]
|
||||
[Components for portable declaration of scoped enums.]
|
||||
]
|
||||
[
|
||||
[[link core.swap swap]]
|
||||
[`boost::swap`]
|
||||
@@ -85,4 +89,5 @@ Currently, the Core library contains:
|
||||
[include:core no_exceptions_support.qbk]
|
||||
[include:core noncopyable.qbk]
|
||||
[include:core null_deleter.qbk]
|
||||
[include:core scoped_enum.qbk]
|
||||
[include:core swap.qbk]
|
||||
|
143
doc/scoped_enum.qbk
Normal file
143
doc/scoped_enum.qbk
Normal file
@@ -0,0 +1,143 @@
|
||||
[section:scoped_enum Headers <boost/core/scoped_enum.hpp>, <boost/core/underlying_type.hpp>]
|
||||
|
||||
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);
|
||||
|
||||
Sample usage:
|
||||
|
||||
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 );
|
||||
|
||||
[heading 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` correcponds 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.
|
||||
|
||||
[heading 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.
|
||||
|
||||
[heading Acknowledgements]
|
||||
|
||||
Thanks to Andrey Semashev for pointing out that emulation through a namespace
|
||||
could not be used within classes.
|
||||
|
||||
Helpful comments and suggestions were also made by Kjell Elster, Phil Endecott,
|
||||
Joel Falcou, Mathias Gaunard, Felipe Magno de Almeida, Matt Calabrese, Vicente
|
||||
Botet, and Daniel James.
|
||||
|
||||
[endsect]
|
@@ -7,125 +7,10 @@
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
/*
|
||||
[section:scoped_enums Scoped Enums]
|
||||
|
||||
Generates C++0x scoped enums if the feature is present, otherwise emulates C++0x
|
||||
scoped enums with C++03 namespaces and enums. The Boost.Config BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
macro is used to detect feature support.
|
||||
|
||||
See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf for a
|
||||
description of the scoped enum feature. Note that the committee changed the name
|
||||
from strongly typed enum to scoped enum.
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
On compilers that don't support them, the library provides two emulations:
|
||||
|
||||
[heading Strict]
|
||||
|
||||
* Able to specify the underlying type.
|
||||
* explicit conversion to/from underlying type.
|
||||
* The wrapper is not a C++03 enum type.
|
||||
|
||||
The user can declare declare these types as
|
||||
|
||||
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 err = future_errc::no_state;
|
||||
|
||||
There are however some limitations:
|
||||
|
||||
* The type 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 macros.
|
||||
|
||||
Instead of
|
||||
|
||||
switch (ev)
|
||||
{
|
||||
case future_errc::broken_promise:
|
||||
// ...
|
||||
|
||||
use
|
||||
|
||||
switch (boost::native_value(ev))
|
||||
{
|
||||
case future_errc::broken_promise:
|
||||
|
||||
And instead of
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
template <>
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
|
||||
#endif
|
||||
|
||||
use
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
template <>
|
||||
struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type > : public true_type { };
|
||||
#endif
|
||||
|
||||
|
||||
Sample usage:
|
||||
|
||||
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 );
|
||||
|
||||
Light
|
||||
Caution: only the syntax is emulated; the semantics are not emulated and
|
||||
the syntax emulation doesn't include being able to specify the underlying
|
||||
representation type.
|
||||
|
||||
The literal scoped emulation is via struct rather than namespace to allow use within classes.
|
||||
Thanks to Andrey Semashev for pointing that out.
|
||||
However the type is an real C++03 enum and so convertible implicitly to an int.
|
||||
|
||||
Sample usage:
|
||||
|
||||
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 );
|
||||
|
||||
Helpful comments and suggestions were also made by Kjell Elster, Phil Endecott,
|
||||
Joel Falcou, Mathias Gaunard, Felipe Magno de Almeida, Matt Calabrese, Vicente
|
||||
Botet, and Daniel James.
|
||||
|
||||
[endsect]
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_CORE_SCOPED_ENUM_HPP
|
||||
#define BOOST_CORE_SCOPED_ENUM_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
@@ -135,22 +20,6 @@ namespace boost
|
||||
{
|
||||
|
||||
#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
/**
|
||||
* Meta-function to get the underlying type of a scoped enum.
|
||||
*
|
||||
* Requires EnumType must be an enum type or the emulation of a scoped enum
|
||||
*/
|
||||
template <typename EnumType>
|
||||
struct underlying_type
|
||||
{
|
||||
/**
|
||||
* The member typedef type names the underlying type of EnumType. It is EnumType::underlying_type when the EnumType is an emulated scoped enum,
|
||||
* std::underlying_type<EnumType>::type when the standard library std::underlying_type is provided.
|
||||
*
|
||||
* The user will need to specialize it when the compiler supports scoped enums but don't provides std::underlying_type.
|
||||
*/
|
||||
typedef typename EnumType::underlying_type type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Meta-function to get the native enum type associated to an enum class or its emulation.
|
||||
@@ -199,12 +68,6 @@ namespace boost
|
||||
|
||||
#else // BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
|
||||
template <typename EnumType>
|
||||
struct underlying_type
|
||||
{
|
||||
//typedef typename std::underlying_type<EnumType>::type type;
|
||||
};
|
||||
|
||||
template <typename EnumType>
|
||||
struct native_type
|
||||
{
|
||||
@@ -222,9 +85,9 @@ namespace boost
|
||||
EnumType native_value(EnumType e)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
}
|
||||
|
||||
|
||||
@@ -233,7 +96,7 @@ namespace boost
|
||||
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
|
||||
|
||||
#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
|
||||
explicit operator underlying_type() const { return get_underlying_value_(); }
|
||||
explicit operator underlying_type() const BOOST_NOEXCEPT { return get_underlying_value_(); }
|
||||
|
||||
#else
|
||||
|
||||
@@ -249,10 +112,11 @@ namespace boost
|
||||
*/
|
||||
#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType, UnderlyingType) \
|
||||
struct EnumType { \
|
||||
typedef void is_boost_scoped_enum_tag; \
|
||||
typedef UnderlyingType underlying_type; \
|
||||
EnumType() BOOST_NOEXCEPT {} \
|
||||
explicit EnumType(underlying_type v) : v_(v) {} \
|
||||
underlying_type get_underlying_value_() const { return v_; } \
|
||||
explicit EnumType(underlying_type v) BOOST_NOEXCEPT : v_(v) {} \
|
||||
underlying_type get_underlying_value_() const BOOST_NOEXCEPT { return v_; } \
|
||||
BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \
|
||||
private: \
|
||||
underlying_type v_; \
|
||||
@@ -299,19 +163,19 @@ namespace boost
|
||||
/**
|
||||
* Name of the native enum type.
|
||||
*
|
||||
* @param NT The new scoped enum.
|
||||
* @param EnumType The new scoped enum.
|
||||
*/
|
||||
#define BOOST_SCOPED_ENUM_NATIVE(EnumType) EnumType::enum_type
|
||||
/**
|
||||
* Forward declares an scoped enum.
|
||||
*
|
||||
* @param NT The scoped enum.
|
||||
* @param EnumType The scoped enum.
|
||||
*/
|
||||
#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(EnumType) struct EnumType
|
||||
|
||||
#else // BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
|
||||
#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,UnderlyingType) enum class EnumType:UnderlyingType
|
||||
#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,UnderlyingType) enum class EnumType : UnderlyingType
|
||||
#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(EnumType) enum class EnumType
|
||||
#define BOOST_SCOPED_ENUM_DECLARE_END2()
|
||||
#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) ;
|
||||
@@ -321,21 +185,9 @@ namespace boost
|
||||
|
||||
#endif // BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
|
||||
// Deprecated macros
|
||||
#define BOOST_SCOPED_ENUM_START(name) BOOST_SCOPED_ENUM_DECLARE_BEGIN(name)
|
||||
#define BOOST_SCOPED_ENUM_END BOOST_SCOPED_ENUM_DECLARE_END2()
|
||||
#define BOOST_SCOPED_ENUM(name) BOOST_SCOPED_ENUM_NATIVE(name)
|
||||
|
||||
//#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
|
||||
//
|
||||
//# define BOOST_SCOPED_ENUM_START(name) struct name { enum enum_type
|
||||
//# define BOOST_SCOPED_ENUM_END };
|
||||
//# define BOOST_SCOPED_ENUM(name) name::enum_type
|
||||
//
|
||||
//#else
|
||||
//
|
||||
//# define BOOST_SCOPED_ENUM_START(name) enum class name
|
||||
//# define BOOST_SCOPED_ENUM_END
|
||||
//# define BOOST_SCOPED_ENUM(name) name
|
||||
//
|
||||
//#endif
|
||||
#endif // BOOST_CORE_SCOPED_ENUM_HPP
|
||||
|
79
include/boost/core/underlying_type.hpp
Normal file
79
include/boost/core/underlying_type.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// underlying_type.hpp ---------------------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes, 2009
|
||||
// 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 http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_CORE_UNDERLYING_TYPE_HPP
|
||||
#define BOOST_CORE_UNDERLYING_TYPE_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// GCC 4.7 and later seem to provide std::underlying_type
|
||||
#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) || (defined(BOOST_GCC) && BOOST_GCC >= 40700 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#include <type_traits>
|
||||
#define BOOST_DETAIL_HAS_STD_UNDERLYING_TYPE
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< typename EnumType, typename Void = void >
|
||||
struct underlying_type_impl;
|
||||
|
||||
#if defined(BOOST_NO_CXX11_SCOPED_ENUMS)
|
||||
|
||||
// Support for boost/core/scoped_enum.hpp
|
||||
template< typename EnumType >
|
||||
struct underlying_type_impl< EnumType, typename EnumType::is_boost_scoped_enum_tag >
|
||||
{
|
||||
/**
|
||||
* The member typedef type names the underlying type of EnumType. It is EnumType::underlying_type when the EnumType is an emulated scoped enum,
|
||||
*/
|
||||
typedef typename EnumType::underlying_type type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_DETAIL_HAS_STD_UNDERLYING_TYPE)
|
||||
|
||||
template< typename EnumType, typename Void >
|
||||
struct underlying_type_impl
|
||||
{
|
||||
typedef typename std::underlying_type< EnumType >::type type;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && !defined(BOOST_DETAIL_HAS_STD_UNDERLYING_TYPE)
|
||||
#define BOOST_NO_UNDERLYING_TYPE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Meta-function to get the underlying type of a scoped enum.
|
||||
*
|
||||
* Requires EnumType must be an enum type or the emulation of a scoped enum.
|
||||
* If BOOST_NO_UNDERLYING_TYPE is defined, the implementation will not be able
|
||||
* to deduce the underlying type of enums. The used is expected to specialize
|
||||
* this trait.
|
||||
*/
|
||||
template< typename EnumType >
|
||||
struct underlying_type :
|
||||
public detail::underlying_type_impl< EnumType >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_CORE_UNDERLYING_TYPE_HPP
|
Reference in New Issue
Block a user