1
0
Fork 0

Codechange: Add to_underlying() to convert enum to underlying type. (#12958)

This simplifies and replaces static_cast and C-style casts doing the same.

`std::to_underlying()` exists in C++23 but not C++20.
pull/12962/head
Peter Nelson 2024-09-22 18:07:42 +01:00 committed by GitHub
parent 376e882a14
commit 0340e19e04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 12 deletions

View File

@ -10,18 +10,22 @@
#ifndef ENUM_TYPE_HPP
#define ENUM_TYPE_HPP
/** Implementation of std::to_underlying (from C++23) */
template <typename enum_type>
constexpr std::underlying_type_t<enum_type> to_underlying(enum_type e) { return static_cast<std::underlying_type_t<enum_type>>(e); }
/** Some enums need to have allowed incrementing (i.e. StationClassID) */
#define DECLARE_POSTFIX_INCREMENT(enum_type) \
inline constexpr enum_type operator ++(enum_type& e, int) \
{ \
enum_type e_org = e; \
e = (enum_type)((std::underlying_type<enum_type>::type)e + 1); \
e = static_cast<enum_type>(to_underlying(e) + 1); \
return e_org; \
} \
inline constexpr enum_type operator --(enum_type& e, int) \
{ \
enum_type e_org = e; \
e = (enum_type)((std::underlying_type<enum_type>::type)e - 1); \
e = static_cast<enum_type>(to_underlying(e) - 1); \
return e_org; \
}
@ -29,19 +33,19 @@
/** Operators to allow to work with enum as with type safe bit set in C++ */
#define DECLARE_ENUM_AS_BIT_SET(enum_type) \
inline constexpr enum_type operator | (enum_type m1, enum_type m2) {return (enum_type)((std::underlying_type<enum_type>::type)m1 | (std::underlying_type<enum_type>::type)m2);} \
inline constexpr enum_type operator & (enum_type m1, enum_type m2) {return (enum_type)((std::underlying_type<enum_type>::type)m1 & (std::underlying_type<enum_type>::type)m2);} \
inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) {return (enum_type)((std::underlying_type<enum_type>::type)m1 ^ (std::underlying_type<enum_type>::type)m2);} \
inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) {m1 = m1 | m2; return m1;} \
inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) {m1 = m1 & m2; return m1;} \
inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) {m1 = m1 ^ m2; return m1;} \
inline constexpr enum_type operator ~(enum_type m) {return (enum_type)(~(std::underlying_type<enum_type>::type)m);}
inline constexpr enum_type operator | (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) | to_underlying(m2)); } \
inline constexpr enum_type operator & (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) & to_underlying(m2)); } \
inline constexpr enum_type operator ^ (enum_type m1, enum_type m2) { return static_cast<enum_type>(to_underlying(m1) ^ to_underlying(m2)); } \
inline constexpr enum_type& operator |= (enum_type& m1, enum_type m2) { m1 = m1 | m2; return m1; } \
inline constexpr enum_type& operator &= (enum_type& m1, enum_type m2) { m1 = m1 & m2; return m1; } \
inline constexpr enum_type& operator ^= (enum_type& m1, enum_type m2) { m1 = m1 ^ m2; return m1; } \
inline constexpr enum_type operator ~(enum_type m) { return static_cast<enum_type>(~to_underlying(m)); }
/** Operator that allows this enumeration to be added to any other enumeration. */
#define DECLARE_ENUM_AS_ADDABLE(EnumType) \
template <typename OtherEnumType, typename = typename std::enable_if<std::is_enum_v<OtherEnumType>, OtherEnumType>::type> \
constexpr OtherEnumType operator + (OtherEnumType m1, EnumType m2) { \
return static_cast<OtherEnumType>(static_cast<typename std::underlying_type<OtherEnumType>::type>(m1) + static_cast<typename std::underlying_type<EnumType>::type>(m2)); \
return static_cast<OtherEnumType>(to_underlying(m1) + to_underlying(m2)); \
}
/**

View File

@ -50,7 +50,7 @@ public:
EndianBufferWriter &operator <<(const T data)
{
if constexpr (std::is_enum_v<T>) {
this->Write(static_cast<std::underlying_type_t<const T>>(data));
this->Write(to_underlying(data));
} else if constexpr (std::is_base_of_v<StrongTypedefBase, T>) {
this->Write(data.base());
} else {

View File

@ -1200,7 +1200,7 @@ int GetEngineProperty(EngineID engine, PropertyID property, int orig_value, cons
*/
bool TestVehicleBuildProbability(Vehicle *v, EngineID engine, BuildProbabilityType type)
{
uint16_t p = GetVehicleCallback(CBID_VEHICLE_BUILD_PROBABILITY, std::underlying_type<BuildProbabilityType>::type(type), 0, engine, v);
uint16_t p = GetVehicleCallback(CBID_VEHICLE_BUILD_PROBABILITY, to_underlying(type), 0, engine, v);
if (p == CALLBACK_FAILED) return false;
const uint16_t PROBABILITY_RANGE = 100;