Заголовок<boost/core/scoped_enum.hpp
>содержит ряд макросов, которые могут быть использованы для генерации C++11 объемных перечней (7.2 [dcl.enum]), если функция поддерживается компилятором, в противном случае эмулировать его с C++03 конструкций.<BOOST_NO_CXX11_SCOPED_ENUMS
>Макро от Boost. Конфигурация используется для обнаружения поддержки функций в компиляторе.
Некоторые из перечислений, определенных в стандартной библиотеке, являются объемными.
enum class future_errc
{
broken_promise,
future_already_retrieved,
promise_already_satisfied,
no_state
};
Пользователь может портативно объявить такое перечисление следующим образом:
BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
{
broken_promise,
future_already_retrieved,
promise_already_satisfied,
no_state
}
BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
Эти макросы позволяют использовать<future_errc
>практически во всех случаях в качестве объемного перечня.
future_errc ev = future_errc::no_state;
Можно указать базовый тип перечисления:
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)
Перечисление поддерживает явное преобразование из базового типа.
Перечисление может быть объявлено вперед:
BOOST_SCOPED_ENUM_FORWARD_DECLARE(future_errc);
Однако есть некоторые ограничения. Во-первых, эмулируемый объемный список не является C++, поэтому<is_enum<
future_errc>
>будет<false_type
>.
Во-вторых, эмулированный объемный список не может быть использован ни в переключателе, ни в шаблонных аргументах. Для этого пользователю необходимо воспользоваться услугами помощников. Вместо того чтобы
switch (ev)
{
case future_errc::broken_promise:
использовать
switch (boost::native_value(ev))
{
case future_errc::broken_promise:
Вместо того, чтобы
template <>
struct is_error_code_enum< future_errc > :
public true_type
{
};
использовать
template <>
struct is_error_code_enum< BOOST_SCOPED_ENUM_NATIVE(future_errc) > :
public true_type
{
};
Наконец, явное преобразование в основной тип должно выполняться с<boost::underlying_cast
>вместо<static_cast
>:
unsigned int val = boost::underlying_cast< unsigned int >(ev);
Вот пример использования:
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 );
В ранних версиях заголовка было два способа объявить ограниченные числа с различными плюсами и минусами для каждого. Другой способ использовал другой набор макросов:
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 );
Здесь<BOOST_SCOPED_ENUM_START
>соответствует<BOOST_SCOPED_ENUM_DECLARE_BEGIN
>,<BOOST_SCOPED_ENUM_END
>-<BOOST_SCOPED_ENUM_DECLARE_END
>и<BOOST_SCOPED_ENUM
>-<BOOST_SCOPED_ENUM_NATIVE
>. Заметьте также полуколонн перед<BOOST_SCOPED_ENUM_END
>.
В текущей версии эти макросы дают эквивалентный результат описанным выше и считаются обесцененными.
Заголовок<boost/core/underlying_type.hpp
>определяет метафункцию<boost::underlying_type
>, которая может быть использована для получения основного типа охватываемого перечня. Эта метафункция поддерживает эмулированные объемные числа, объявленные макросами<boost/core/scoped_enum.hpp
>. Когда собственные объемные числа поддерживаются компилятором, эта метафункция эквивалентна<std::underlying_type
>.
К сожалению, существуют конфигурации, которые реализуют ограниченные числа, но не<std::underlying_type
>. В этом случае<boost::underlying_type
>должен быть специализирован пользователем. Макро<BOOST_NO_UNDERLYING_TYPE
>обозначает такие случаи.