如何在 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
与无作用域枚举不同,有作用域枚举不能“隐式”转换为其整数值。您需要使用强制转换显式地将其转换为整数:
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;
提供的 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;
}
enum class Color
{
Red = 1,
Green = 11,
Blue = 111
};
int value = static_cast<int>(Color::Blue); // 111
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);
}
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);
}
(在 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);
}
。它提供流运算符并打印名称字符串而不是整数值:
#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';
}
//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;