mirror of https://github.com/OpenTTD/OpenTTD
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
parent
376e882a14
commit
0340e19e04
|
@ -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)); \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue