如何在C++11中输出枚举类的值
How can I output the value of an enum class in C++11
如何在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;
#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;
}
可以让第二个示例(即使用作用域枚举的示例)使用与未作用域枚举相同的语法。此外,该解决方案是通用的,适用于所有作用域枚举,而不是为每个作用域枚举编写代码(如@ForEveR提供的答案所示)。
解决方案是编写一个适用于任何作用域枚举的通用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
(我还不允许发表评论。)我建议对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++中使用枚举作为标志?
根据@TobyPeight:的建议,还有一种(更好的)没有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);
}
以下内容在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);
}
由于c++23存在
std::to_underlying
的作用与所有其他答案相同,但它在标准中
根据James McNellis的出色回答,如果您的编译器支持Concepts and Constraints(在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);
}
您可以这样做:
//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;
相关文章:
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 为什么我的开关/机箱在使用枚举时默认?
- 标准::可选枚举的比较运算符
- C++两个源文件之间共享的枚举的静态实例
- 在 C++ 中输出枚举类类型的向量元素
- 枚举输出的值错误
- 如何重载<<以输出枚举的字符串值
- 如何在C++11中输出枚举类的值
- C++ 简单的输入/输出程序 + 枚举器
- 输出结构的枚举返回负数
- C++ 诡计:输出实际枚举,而不是其值