如何在C++11中输出枚举类的值

问题描述 投票:0回答:10

如何在 C++11 中输出

enum class
的值?在 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

c++ c++11 templates enums enum-class
10个回答
178
投票

与无作用域枚举不同,有作用域枚举不能“隐式”转换为其整数值。您需要使用强制转换显式地将其转换为整数: 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;



51
投票


24
投票
@ForEveR

提供的 answer 所示)。 解决方案是编写一个通用的

operator<<

函数,该函数适用于任何作用域枚举。该解决方案通过

std::enable_if 使用 SFINAE
,如下所示。
#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; }



22
投票

enum class Color { Red = 1, Green = 11, Blue = 111 }; int value = static_cast<int>(Color::Blue); // 111



11
投票

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
    :“确保”编译时该函数执行某项操作。按照建议,仅使用枚举
    
    
    
  • 顺便说一句,我问自己:当我想为我的枚举成员分配数值时,为什么要使用
enum class

?!考虑到转换工作。


也许我会回到普通的

enum

,正如我在这里建议的:

How to use enums as flags in C++?

基于@TobySpeight的建议,没有 static_assert 的另一种(更好)风格:

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); }



3
投票

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); }




1
投票
概念和约束

(在 C++20 中引入),它可以用于引入额外的编译时理智(例如,更清楚地指示任何不正确的情况)用法)通过以下简单的方式添加到函数模板中: template<typename E> concept EnumType = std::is_enum_v<E>; template <EnumType E> constexpr std::underlying_type_t<E> enumUnderlyingType(E const underlying_type) { return static_cast<std::underlying_type_t<E>>(underlying_type); }



0
投票
magic_enum

。它提供流运算符并打印名称字符串而不是整数值: #include <magic_enum/magic_enum_iostream.hpp> #include <iostream> using magic_enum::iostream_operators::operator<<; // out-of-the-box ostream operators for enums.. int main() { enum class Color { RED, GREEN, BLUE}; Color c = Color::BLUE; std::cout << c << '\n'; }

参见 Godbolt


-2
投票

//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;

© www.soinside.com 2019 - 2024. All rights reserved.