-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathis_scoped_enum.h
93 lines (77 loc) · 2.78 KB
/
is_scoped_enum.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#ifndef COOL_IS_SCOPED_ENUM_H_
#define COOL_IS_SCOPED_ENUM_H_
#include <type_traits>
namespace cool {
///////////////////////////////////////////////////////////////////////////
// underlying_type<E>
//
// This is the C++20 version of std::underlying_type backported to C++11
//
// If T is a complete enumeration (enum) type, provides a member typedef type
// that names the underlying type of T.
// Otherwise, if T is not an enumeration type, there is no member type.
// Otherwise (T is an incomplete enumeration type), the program is ill-formed.
///////////////////////////////////////////////////////////////////////////
#if __cplusplus >= 202002
using std::underlying_type;
using std::underlying_type_t;
#else
namespace detail {
template <typename E, bool = std::is_enum<E>::value>
struct underlying_type {};
template <typename E>
struct underlying_type<E, true> {
using type = typename std::underlying_type<E>::type;
};
} // namespace detail
template <typename E>
using underlying_type = detail::underlying_type<E>;
template <typename E>
using underlying_type_t = typename underlying_type<E>::type;
#endif
///////////////////////////////////////////////////////////////////////////
// to_underlying
//
// This is the C++23 version of std::to_underlying backported
// Converts an enumeration to its underlying type.
///////////////////////////////////////////////////////////////////////////
#if defined(__cpp_lib_to_underlying)
using std::to_underlying;
#else
template <typename E>
constexpr underlying_type_t<E> to_underlying(E e) noexcept {
return static_cast<underlying_type_t<E>>(e);
}
#endif
///////////////////////////////////////////////////////////////////////////
// is_scoped_enum
//
// This is the C++ 23 version of std::to_underlying backported
// Checks whether T is a scoped enumeration type.
// Provides the member constant
// value which is equal to true, if T is a scoped enumeration type.
// Otherwise, value is equal to false.
///////////////////////////////////////////////////////////////////////////
#if defined(__cpp_lib_is_scoped_enum)
using std::is_scoped_enum;
using std::is_scoped_enum_v;
#else
namespace detail {
template <typename E, bool = std::is_enum<E>::value>
struct is_scoped_enum : std::false_type {};
template <typename E>
struct is_scoped_enum<E, true>
: std::integral_constant<
bool, !std::is_convertible<E, underlying_type_t<E>>::value> {};
} // namespace detail
template <typename E>
struct is_scoped_enum : detail::is_scoped_enum<E>::type {};
// Technically, this needs C++17 and __cpp_inline_variables,
// but it compiles with clang++-11 and g++-11 in C++11 mode
//#if defined(__cpp_inline_variables)
template <typename E>
inline constexpr bool is_scoped_enum_v = is_scoped_enum<E>::value;
//#endif
#endif
} // namespace cool
#endif /* IS_SCOPED_ENUM_H_ */