123

如何enum class在 C++11 中输出 an 的值?在 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编译

4

8 回答 8

152

与无范围枚举不同,有范围枚举不能隐式转换为其整数值。您需要使用强制转换将其显式转换为整数:

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;
于 2012-07-10T20:32:20.277 回答
44
#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;
}
于 2012-07-10T20:33:41.400 回答
24

可以使您的第二个示例(即使用范围枚举的示例)使用与无范围枚举相同的语法来工作。此外,该解决方案是通用的,适用于所有范围枚举,而不是为每个范围枚举编写代码(如@ForEveR提供的答案所示)。

解决方案是编写一个operator<<适用于任何范围枚举的通用函数。解决方案采用SFINAE via std::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;
}
于 2015-01-29T04:02:12.413 回答
16

为了写得更简单,

enum class Color
{
    Red = 1,
    Green = 11,
    Blue = 111
};

int value = static_cast<int>(Color::Blue); // 111
于 2019-01-31T14:41:59.060 回答
10

(我还不允许发表评论。)我建议对 James McNellis 已经很好的答案进行以下改进:

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如何在 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);
}
于 2014-11-07T19:57:27.737 回答
3

以下在 C++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);
}
于 2019-07-20T09:04:10.813 回答
1

由于 c++23 有

std::to_underlying它与所有其他答案的作用相同,但它在 std

于 2021-10-22T08:10:15.637 回答
0

你可以这样做:

//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;
于 2019-10-02T16:37:46.443 回答