mirror of https://github.com/OpenTTD/OpenTTD
Codechange: prepare the pool for strongly typed pool element IDs
parent
82c5e37b46
commit
30127dfe90
|
@ -241,7 +241,7 @@ struct SpecializedStation : public BaseStation {
|
||||||
* @param index tested index
|
* @param index tested index
|
||||||
* @return is this index valid index of T?
|
* @return is this index valid index of T?
|
||||||
*/
|
*/
|
||||||
static inline bool IsValidID(size_t index)
|
static inline bool IsValidID(auto index)
|
||||||
{
|
{
|
||||||
return BaseStation::IsValidID(index) && IsExpected(BaseStation::Get(index));
|
return BaseStation::IsValidID(index) && IsExpected(BaseStation::Get(index));
|
||||||
}
|
}
|
||||||
|
@ -250,7 +250,7 @@ struct SpecializedStation : public BaseStation {
|
||||||
* Gets station with given index
|
* Gets station with given index
|
||||||
* @return pointer to station with given index casted to T *
|
* @return pointer to station with given index casted to T *
|
||||||
*/
|
*/
|
||||||
static inline T *Get(size_t index)
|
static inline T *Get(auto index)
|
||||||
{
|
{
|
||||||
return (T *)BaseStation::Get(index);
|
return (T *)BaseStation::Get(index);
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ struct SpecializedStation : public BaseStation {
|
||||||
* Returns station if the index is a valid index for this station type
|
* Returns station if the index is a valid index for this station type
|
||||||
* @return pointer to station with given index if it's a station of this type
|
* @return pointer to station with given index if it's a station of this type
|
||||||
*/
|
*/
|
||||||
static inline T *GetIfValid(size_t index)
|
static inline T *GetIfValid(auto index)
|
||||||
{
|
{
|
||||||
return IsValidID(index) ? Get(index) : nullptr;
|
return IsValidID(index) ? Get(index) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,12 @@ DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index)
|
||||||
}
|
}
|
||||||
this->data[index] = item;
|
this->data[index] = item;
|
||||||
SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
|
SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
|
||||||
item->index = (Tindex)(uint)index;
|
if constexpr (std::is_base_of_v<PoolIDBase, Tindex>) {
|
||||||
|
/* MSVC complains about casting to narrower type, so first cast to the base type... then to the strong type. */
|
||||||
|
item->index = static_cast<Tindex>(static_cast<Tindex::BaseType>(index));
|
||||||
|
} else {
|
||||||
|
item->index = static_cast<Tindex>(index);
|
||||||
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,54 @@ static constexpr PoolTypes PT_ALL = {PoolType::Normal, PoolType::NetworkClient,
|
||||||
|
|
||||||
typedef std::vector<struct PoolBase *> PoolVector; ///< Vector of pointers to PoolBase
|
typedef std::vector<struct PoolBase *> PoolVector; ///< Vector of pointers to PoolBase
|
||||||
|
|
||||||
|
/** Non-templated base for #PoolID for use with type trait queries. */
|
||||||
|
struct PoolIDBase {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templated helper to make a PoolID a single POD value.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
*
|
||||||
|
* using MyType = PoolID<int, struct MyTypeTag, 16, 0xFF>;
|
||||||
|
*
|
||||||
|
* @tparam TBaseType Type of the derived class (i.e. the concrete usage of this class).
|
||||||
|
* @tparam TTag An unique struct to keep types of the same TBaseType distinct.
|
||||||
|
* @tparam TEnd The PoolID at the end of the pool (equivalent to size).
|
||||||
|
* @tparam TInvalid The PoolID denoting an invalid value.
|
||||||
|
*/
|
||||||
|
template <typename TBaseType, typename TTag, TBaseType TEnd, TBaseType TInvalid>
|
||||||
|
struct EMPTY_BASES PoolID : PoolIDBase {
|
||||||
|
using BaseType = TBaseType;
|
||||||
|
|
||||||
|
constexpr PoolID() = default;
|
||||||
|
constexpr PoolID(const PoolID &) = default;
|
||||||
|
constexpr PoolID(PoolID &&) = default;
|
||||||
|
|
||||||
|
explicit constexpr PoolID(const TBaseType &value) : value(value) {}
|
||||||
|
|
||||||
|
constexpr PoolID &operator =(const PoolID &rhs) { this->value = rhs.value; return *this; }
|
||||||
|
constexpr PoolID &operator =(PoolID &&rhs) { this->value = std::move(rhs.value); return *this; }
|
||||||
|
|
||||||
|
/* Only allow conversion to BaseType via method. */
|
||||||
|
constexpr TBaseType base() const noexcept { return this->value; }
|
||||||
|
|
||||||
|
static constexpr PoolID Begin() { return PoolID{}; }
|
||||||
|
static constexpr PoolID End() { return PoolID{static_cast<TBaseType>(TEnd)}; }
|
||||||
|
static constexpr PoolID Invalid() { return PoolID{static_cast<TBaseType>(TInvalid)}; }
|
||||||
|
|
||||||
|
constexpr auto operator++() { ++this->value; return this; }
|
||||||
|
constexpr auto operator+(const std::integral auto &val) const { return this->value + val; }
|
||||||
|
|
||||||
|
constexpr bool operator==(const PoolID<TBaseType, TTag, TEnd, TInvalid> &rhs) const { return this->value == rhs.value; }
|
||||||
|
constexpr auto operator<=>(const PoolID<TBaseType, TTag, TEnd, TInvalid> &rhs) const { return this->value <=> rhs.value; }
|
||||||
|
|
||||||
|
constexpr bool operator==(const size_t &rhs) const { return this->value == rhs; }
|
||||||
|
constexpr auto operator<=>(const size_t &rhs) const { return this->value <=> rhs; }
|
||||||
|
private:
|
||||||
|
/* Do not explicitly initialize. */
|
||||||
|
TBaseType value;
|
||||||
|
};
|
||||||
|
|
||||||
/** Base class for base of all pools. */
|
/** Base class for base of all pools. */
|
||||||
struct PoolBase {
|
struct PoolBase {
|
||||||
const PoolType type; ///< Type of this pool.
|
const PoolType type; ///< Type of this pool.
|
||||||
|
@ -83,6 +131,8 @@ private:
|
||||||
static constexpr size_t GetMaxIndexValue(T) { return std::numeric_limits<T>::max(); }
|
static constexpr size_t GetMaxIndexValue(T) { return std::numeric_limits<T>::max(); }
|
||||||
template <typename T> requires std::is_enum_v<T>
|
template <typename T> requires std::is_enum_v<T>
|
||||||
static constexpr size_t GetMaxIndexValue(T) { return std::numeric_limits<std::underlying_type_t<T>>::max(); }
|
static constexpr size_t GetMaxIndexValue(T) { return std::numeric_limits<std::underlying_type_t<T>>::max(); }
|
||||||
|
template <typename T> requires std::is_base_of_v<PoolIDBase, T>
|
||||||
|
static constexpr size_t GetMaxIndexValue(T) { return std::numeric_limits<typename T::BaseType>::max(); }
|
||||||
public:
|
public:
|
||||||
/* Ensure the highest possible index, i.e. Tmax_size -1, is within the bounds of Tindex. */
|
/* Ensure the highest possible index, i.e. Tmax_size -1, is within the bounds of Tindex. */
|
||||||
static_assert(Tmax_size - 1 <= GetMaxIndexValue(Tindex{}));
|
static_assert(Tmax_size - 1 <= GetMaxIndexValue(Tindex{}));
|
||||||
|
@ -263,8 +313,8 @@ public:
|
||||||
{
|
{
|
||||||
if (p == nullptr) return;
|
if (p == nullptr) return;
|
||||||
Titem *pn = static_cast<Titem *>(p);
|
Titem *pn = static_cast<Titem *>(p);
|
||||||
assert(pn == Tpool->Get(pn->index));
|
assert(pn == Tpool->Get(Pool::GetRawIndex(pn->index)));
|
||||||
Tpool->FreeItem(pn->index);
|
Tpool->FreeItem(Pool::GetRawIndex(pn->index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -328,9 +378,9 @@ public:
|
||||||
* @param index index to examine
|
* @param index index to examine
|
||||||
* @return true if PoolItem::Get(index) will return non-nullptr pointer
|
* @return true if PoolItem::Get(index) will return non-nullptr pointer
|
||||||
*/
|
*/
|
||||||
static inline bool IsValidID(size_t index)
|
static inline bool IsValidID(auto index)
|
||||||
{
|
{
|
||||||
return Tpool->IsValidID(index);
|
return Tpool->IsValidID(GetRawIndex(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -339,9 +389,9 @@ public:
|
||||||
* @return pointer to Titem
|
* @return pointer to Titem
|
||||||
* @pre index < this->first_unused
|
* @pre index < this->first_unused
|
||||||
*/
|
*/
|
||||||
static inline Titem *Get(size_t index)
|
static inline Titem *Get(auto index)
|
||||||
{
|
{
|
||||||
return Tpool->Get(index);
|
return Tpool->Get(GetRawIndex(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -350,9 +400,9 @@ public:
|
||||||
* @return pointer to Titem
|
* @return pointer to Titem
|
||||||
* @note returns nullptr for invalid index
|
* @note returns nullptr for invalid index
|
||||||
*/
|
*/
|
||||||
static inline Titem *GetIfValid(size_t index)
|
static inline Titem *GetIfValid(auto index)
|
||||||
{
|
{
|
||||||
return index < Tpool->first_unused ? Tpool->Get(index) : nullptr;
|
return GetRawIndex(index) < Tpool->first_unused ? Tpool->Get(GetRawIndex(index)) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -414,6 +464,11 @@ private:
|
||||||
void *GetNew(size_t size, size_t index);
|
void *GetNew(size_t size, size_t index);
|
||||||
|
|
||||||
void FreeItem(size_t index);
|
void FreeItem(size_t index);
|
||||||
|
|
||||||
|
/* Temporary helper functions to get the raw index from either strongly and non-strongly typed pool items. */
|
||||||
|
static constexpr size_t GetRawIndex(size_t index) { return index; }
|
||||||
|
template <typename T> requires std::is_base_of_v<PoolIDBase, T>
|
||||||
|
static constexpr size_t GetRawIndex(const T &index) { return index.base(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POOL_TYPE_HPP */
|
#endif /* POOL_TYPE_HPP */
|
||||||
|
|
|
@ -1177,7 +1177,7 @@ struct SpecializedVehicle : public Vehicle {
|
||||||
* @param index tested index
|
* @param index tested index
|
||||||
* @return is this index valid index of T?
|
* @return is this index valid index of T?
|
||||||
*/
|
*/
|
||||||
static inline bool IsValidID(size_t index)
|
static inline bool IsValidID(auto index)
|
||||||
{
|
{
|
||||||
return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
|
return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
|
||||||
}
|
}
|
||||||
|
@ -1186,7 +1186,7 @@ struct SpecializedVehicle : public Vehicle {
|
||||||
* Gets vehicle with given index
|
* Gets vehicle with given index
|
||||||
* @return pointer to vehicle with given index casted to T *
|
* @return pointer to vehicle with given index casted to T *
|
||||||
*/
|
*/
|
||||||
static inline T *Get(size_t index)
|
static inline T *Get(auto index)
|
||||||
{
|
{
|
||||||
return (T *)Vehicle::Get(index);
|
return (T *)Vehicle::Get(index);
|
||||||
}
|
}
|
||||||
|
@ -1195,7 +1195,7 @@ struct SpecializedVehicle : public Vehicle {
|
||||||
* Returns vehicle if the index is a valid index for this vehicle type
|
* Returns vehicle if the index is a valid index for this vehicle type
|
||||||
* @return pointer to vehicle with given index if it's a vehicle of this type
|
* @return pointer to vehicle with given index if it's a vehicle of this type
|
||||||
*/
|
*/
|
||||||
static inline T *GetIfValid(size_t index)
|
static inline T *GetIfValid(auto index)
|
||||||
{
|
{
|
||||||
return IsValidID(index) ? Get(index) : nullptr;
|
return IsValidID(index) ? Get(index) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue