Как я могу вывести значение enum class
в C ++ 11? В C ++ 03 это так:
#include <iostream>
using namespace std;
enum A {
a = 1,
b = 69,
c= 666
};
int main () {
A a = A::c;
cout << a << endl;
}
в c ++ 0x этот код не компилируется
#include <iostream>
using namespace std;
enum class A {
a = 1,
b = 69,
c= 666
};
int main () {
A a = A::c;
cout << a << endl;
}
prog.cpp:13:11: error: cannot bind 'std::ostream' lvalue to 'std::basic_ostream<char>&&'
/usr/lib/gcc/i686-pc-linux-gnu/4.5.1/../../../../include/c++/4.5.1/ostream:579:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = A]'
скомпилировано на Ideone.com
Ответы:
В отличие от перечисления с незаданной областью, перечисление с заданной областью не может быть неявно преобразовано в целое число. Вам нужно явно преобразовать его в целое число, используя приведение:
std::cout << static_cast<std::underlying_type<A>::type>(a) << std::endl;
Вы можете захотеть инкапсулировать логику в шаблон функции:
template <typename Enumeration> auto as_integer(Enumeration const value) -> typename std::underlying_type<Enumeration>::type { return static_cast<typename std::underlying_type<Enumeration>::type>(value); }
используется в качестве:
std::cout << as_integer(a) << std::endl;
источник
as_integer
с одного из моих открытых источников библиотек, CxxReflect (см enumeration.hpp ). Библиотека последовательно и везде использует конечные возвращаемые типы. Для последовательности.as_integer
можно определитьconstexpr
так, чтобы его можно было использовать в контекстах, где необходимо постоянное выражение.#include <iostream> #include <type_traits> using namespace std; enum class A { a = 1, b = 69, c= 666 }; std::ostream& operator << (std::ostream& os, const A& obj) { os << static_cast<std::underlying_type<A>::type>(obj); return os; } int main () { A a = A::c; cout << a << endl; }
источник
g++ -std=c++0x enum.cpp
но получаю кучу ошибок компилятора -> pastebin.com/JAtLXan9 . Я также не смог скомпилировать пример от @ james-mcnellis.Можно заставить ваш второй пример (то есть тот, который использует перечисление с ограниченной областью действия) работать с использованием того же синтаксиса, что и перечисления без области действия. Кроме того, решение является универсальным и будет работать для всех перечислений с областью действия, а не для написания кода для каждого перечисления с областью действия (как показано в ответе, предоставленном @ForEveR ).
Решение состоит в том, чтобы написать универсальную
operator<<
функцию, которая будет работать для любого перечисления с ограниченной областью видимости. Решение использует SFINAE viastd::enable_if
и выглядит следующим образом.#include <iostream> #include <type_traits> // Scoped enum enum class Color { Red, Green, Blue }; // Unscoped enum enum Orientation { Horizontal, Vertical }; // Another scoped enum enum class ExecStatus { Idle, Started, Running }; template<typename T> std::ostream& operator<<(typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e) { return stream << static_cast<typename std::underlying_type<T>::type>(e); } int main() { std::cout << Color::Blue << "\n"; std::cout << Vertical << "\n"; std::cout << ExecStatus::Running << "\n"; return 0; }
источник
typename
раньшеstd::underlying_type<T>::type
.error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
. это похоже на то, что, когда поток является временным, ADL не работает, и указанный выше шаблон невозможен. какие-нибудь советы?cout
оператора в одинcout
оператор, связав<<
операторы вместе. Смотрите здесь(Мне пока не разрешено комментировать.) Я бы предложил следующие улучшения и без того отличного ответа Джеймса Макнеллиса:
template <typename Enumeration> constexpr auto as_integer(Enumeration const value) -> typename std::underlying_type<Enumeration>::type { static_assert(std::is_enum<Enumeration>::value, "parameter is not of type enum or enum class"); return static_cast<typename std::underlying_type<Enumeration>::type>(value); }
с участием
constexpr
: позволяет мне использовать значение члена перечисления как размер массива времени компиляцииstatic_assert
+is_enum
: чтобы во время компиляции "гарантировать" выполнение функцией sth. только с перечислениями, как предлагаетсяКстати, я спрашиваю себя: зачем мне вообще использовать,
enum class
когда я хотел бы присвоить числовые значения членам моего перечисления ?! Учитывая усилия по конверсии.Возможно, я бы тогда вернулся к обычному,
enum
как я предлагал здесь: как использовать перечисления в качестве флагов в C ++?Еще один (лучший) вариант без static_assert, основанный на предложении @TobySpeight:
template <typename Enumeration> constexpr std::enable_if_t<std::is_enum<Enumeration>::value, std::underlying_type_t<Enumeration>> as_number(const Enumeration value) { return static_cast<std::underlying_type_t<Enumeration>>(value); }
источник
T
которыйstd::underlying_type<T>::type
существует, ноstd::is_enum<T>::value
является ложным? Если нет, тоstatic_assert
ценность не увеличивается.Enumeration
это не полный тип перечисления. В этом случае может быть уже слишком поздно, поскольку он используется в возвращаемом типе. Может, мы могли бы указатьstd::enable_if<std::is_enum<Enumeration>::value, std::underlying_type<Enumeration>::type>
в качестве возвращаемого типа? Конечно, это намного проще (и сообщения об ошибках намного яснее), если у вас есть компилятор с поддержкой концепций ...Чтобы писать проще,
enum class Color { Red = 1, Green = 11, Blue = 111 }; int value = static_cast<int>(Color::Blue); // 111
источник
Следующее сработало для меня в С ++ 11:
template <typename Enum> constexpr typename std::enable_if<std::is_enum<Enum>::value, typename std::underlying_type<Enum>::type>::type to_integral(Enum const& value) { return static_cast<typename std::underlying_type<Enum>::type>(value); }
источник
Вы можете сделать что-то вроде этого:
//outside of main namespace A { enum A { a = 0, b = 69, c = 666 }; }; //in main: A::A a = A::c; std::cout << a << std::endl;
источник