#include <iostream>
struct a {
enum LOCAL_A { A1, A2 };
};
enum class b { B1, B2 };
int foo(int input) { return input; }
int main(void) {
std::cout << foo(a::A1) << std::endl;
std::cout << foo(static_cast<int>(b::B2)) << std::endl;
}
그만큼 a::LOCAL_A
강력한 형식의 열거 형이 달성하려고하는 것이지만 약간의 차이가 있습니다. 일반 열거 형은 정수 유형으로 변환 할 수 있지만 강력한 형식의 열거 형은 캐스트 없이는 할 수 없습니다.
그렇다면 강력한 유형의 열거 형 값을 캐스트없이 정수 유형으로 변환하는 방법이 있습니까? 그렇다면 어떻게?
답변
질문에서 언급 한대로 문제를 해결할뿐만 아니라 여러 문제를 해결하기위한 강력한 유형의 열거 형 :
- 형식 안전을 제공하여 완전한 승격으로 정수로의 암시 적 변환을 제거합니다.
- 기본 유형을 지정하십시오.
- 강력한 범위 지정을 제공하십시오.
따라서 강력한 형식의 열거 형을 정수 또는 기본 형식으로 암시 적으로 변환하는 것은 불가능합니다. 따라서 static_cast
변환을 명시 적으로 작성해야합니다.
유일한 문제가 범위를 정하고 정수로 암시 적 승격을 원한다면 선언 된 구조의 범위와 함께 강력하게 형식이 지정된 열거 형을 사용하는 것이 좋습니다.
답변
다른 사람들이 말했듯이 암시 적 변환을 할 수 없으며 의도적으로 설계된 것입니다.
원하는 경우 캐스트에서 기본 유형을 지정할 필요가 없습니다.
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
return static_cast<typename std::underlying_type<E>::type>(e);
}
std::cout << foo(to_underlying(b::B2)) << std::endl;
답변
R. Martinho Fernandes 가 제공 한 C ++ 14 버전의 답변 은 다음과 같습니다.
#include <type_traits>
template <typename E>
constexpr auto to_underlying(E e) noexcept
{
return static_cast<std::underlying_type_t<E>>(e);
}
이전 답변과 마찬가지로 모든 종류의 열거 형 및 기본 유형에서 작동합니다. noexcept
예외가 발생하지 않으므로 키워드를 추가했습니다 .
업데이트
이것은 Scott Meyers의 Effective Modern C ++ 에도 나타납니다 . 항목 10을 참조하십시오 (이 책의 사본에있는 항목의 마지막 페이지에 자세히 나와 있습니다).
답변
#include <cstdlib>
#include <cstdio>
#include <cstdint>
#include <type_traits>
namespace utils
{
namespace details
{
template< typename E >
using enable_enum_t = typename std::enable_if< std::is_enum<E>::value,
typename std::underlying_type<E>::type
>::type;
} // namespace details
template< typename E >
constexpr inline details::enable_enum_t<E> underlying_value( E e )noexcept
{
return static_cast< typename std::underlying_type<E>::type >( e );
}
template< typename E , typename T>
constexpr inline typename std::enable_if< std::is_enum<E>::value &&
std::is_integral<T>::value, E
>::type
to_enum( T value ) noexcept
{
return static_cast<E>( value );
}
} // namespace utils
int main()
{
enum class E{ a = 1, b = 3, c = 5 };
constexpr auto a = utils::underlying_value(E::a);
constexpr E b = utils::to_enum<E>(5);
constexpr auto bv = utils::underlying_value(b);
printf("a = %d, b = %d", a,bv);
return 0;
}
답변
아니요. 자연적인 방법 은 없습니다 .
실제로 enum class
C ++ 11에서 강력하게 입력 한 동기 중 하나 는으로의 자동 변환을 방지하는 것 int
입니다.
답변
암묵적인 변환이없는 이유는 (설계에 의한) 다른 답변에서 제시되었습니다.
나는 개인적 operator+
으로 열거 형 클래스에서 기본 유형으로 변환 하기 위해 단항 을 사용 합니다.
template <typename T>
constexpr auto operator+(T e) noexcept
-> std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>>
{
return static_cast<std::underlying_type_t<T>>(e);
}
“타이핑 오버 헤드”는 거의 없습니다.
std::cout << foo(+b::B2) << std::endl;
실제로 매크로를 사용하여 열거 형과 연산자 기능을 한 번에 생성합니다.
#define UNSIGNED_ENUM_CLASS(name, ...) enum class name : unsigned { __VA_ARGS__ };\
inline constexpr unsigned operator+ (name const val) { return static_cast<unsigned>(val); }
답변
이것이 당신이나 다른 누군가를 돕기를 바랍니다.
enum class EnumClass : int //set size for enum
{
Zero, One, Two, Three, Four
};
union Union //This will allow us to convert
{
EnumClass ec;
int i;
};
int main()
{
using namespace std;
//convert from strongly typed enum to int
Union un2;
un2.ec = EnumClass::Three;
cout << "un2.i = " << un2.i << endl;
//convert from int to strongly typed enum
Union un;
un.i = 0;
if(un.ec == EnumClass::Zero) cout << "True" << endl;
return 0;
}