Mam klase HandleBase
, która jest taką ogólną klasą trzymającą ID
struct HandleBase
{
using HandleID = uint32_t;
static constexpr HandleID INVALID_HANDLE_ID = HandleID{ std::numeric_limits<HandleID>::max() };
HandleBase() = default;
HandleBase(HandleID ID)
: object(ID) {}
inline void clear() { object = INVALID_HANDLE_ID; }
inline auto operator<=>(const HandleBase& other) const { return object <=> other.object; }
[[nodiscard]] inline HandleID getID() const { return object; }
protected:
HandleID object = INVALID_HANDLE_ID;
};
i klasę, Handle
, która jest template i jako T
podaje się jakąś klasę, na którą wskazuje ten ID
template <typename T>
struct Handle : HandleBase
{
using HandleBase::HandleBase;
template<typename U>
Handle(const Handle<U>& base)
: HandleBase(base)
{
}
};
mam też klasę, która posiada właśnie ten ID
struct Object
{
Handle<Object> ID;
};
i konkretną implementację jakiegoś obiektu
struct ObjectA : Object
{};
oraz klasę, która jest interfejsem do zarządzania obiektami. Ma ona metodę wirtualną, która przyjmuje jako parameter właśnie Handle
struct ObjectManager
{
virtual Object* getObjectByID(Handle<Object> handle) = 0;
};
i konkretną implementacje menażdżera obiektu A
struct ObjectAManager : ObjectManager
{
ObjectA* getObjectByID(Handle<ObjectA> handle) override {//... coś tam}
};
no i wszystko fajnie, tylko, że podczas kompilacji pokazuje się błąd, że ObjectAManager
did not override any base class methods
.
gdy zamiast Handle<Object>
w ObjectManager
i Handle<ObjectA>
w ObjectAManager
dam po prostu uint32_t
działa ideolo, bo wiadomo, int to int, ale chciałbym posługiwać się klasą Handle
W jaki sposób to zrobić?
próbowałem dodać
auto operator uint32_t() const { return object }
do klasy HandleBase
żeby może kompilator spróbował potraktować te klasy jako uint32_t
ale nie zadziałało.
Jest jakiś sposób na to żeby nie było erroru did not override any base class methods
?
edit
użycie
std::vector<ObjectA> objects;
for(uint32_t i = 0; i < 10; ++i) {
auto& object = objects.emplace_back();
object.id = Handle<ObjectA>(i);
}
ObjectAManager manager;
auto fifthObjectHandle = Handle<ObjectA>{5};
ObjectA fifthObject = manager.getObjectByID(fifthObjectHandle);
ObjectManager
nigdy nie będzie używany czy tworzony przez "end usera". Jest używany tylko do innych internalowych klas.
Gdy np. pojawi się ObjectB, to musi on mieć swój manager ObjectBManager
i "end user" używa tego konkretnego managera