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;
답변
#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;
}
답변
범위가 지정되지 않은 enum과 동일한 구문을 사용하여 작동하도록 두 번째 예제 (즉, 범위가 지정된 enum을 사용하는 예제)를 얻을 수 있습니다. 또한 솔루션은 일반적이며 모든 범위가 지정된 열거 형에 대해 작동하지만 각 범위가 지정된 열거 형에 대한 코드를 작성합니다 ( @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;
}
답변
(아직 언급 할 수 없습니다.) 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);
}
답변
더 간단하게 작성하려면
enum class Color
{
Red = 1,
Green = 11,
Blue = 111
};
int value = static_cast<int>(Color::Blue); // 111
답변
다음은 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);
}
답변
다음과 같이 할 수 있습니다.
//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;