From 6fb376f1cf6102f5f0d17053f68c2105b16f9348 Mon Sep 17 00:00:00 2001 From: Bo Svensson <90132211+bosvensson1@users.noreply.github.com> Date: Mon, 25 Oct 2021 07:08:50 +0000 Subject: [PATCH] templatise ptr.hpp (#3185) With this PR we consolidate identical logic for Ptr and ConstPtr with the help of a template. --- apps/openmw/mwworld/livecellref.cpp | 5 + apps/openmw/mwworld/livecellref.hpp | 3 + apps/openmw/mwworld/ptr.cpp | 89 ----------- apps/openmw/mwworld/ptr.hpp | 228 ++++++++-------------------- 4 files changed, 72 insertions(+), 253 deletions(-) delete mode 100644 apps/openmw/mwworld/ptr.cpp diff --git a/apps/openmw/mwworld/livecellref.cpp b/apps/openmw/mwworld/livecellref.cpp index c74817911e..62c9f3a2f0 100644 --- a/apps/openmw/mwworld/livecellref.cpp +++ b/apps/openmw/mwworld/livecellref.cpp @@ -73,3 +73,8 @@ bool MWWorld::LiveCellRefBase::checkStateImp (const ESM::ObjectState& state) { return true; } + +unsigned int MWWorld::LiveCellRefBase::getType() const +{ + return mClass->getType(); +} diff --git a/apps/openmw/mwworld/livecellref.hpp b/apps/openmw/mwworld/livecellref.hpp index 48e237bce4..1ead0395fd 100644 --- a/apps/openmw/mwworld/livecellref.hpp +++ b/apps/openmw/mwworld/livecellref.hpp @@ -43,6 +43,9 @@ namespace MWWorld virtual std::string_view getTypeDescription() const = 0; + unsigned int getType() const; + ///< @see MWWorld::Class::getType + protected: void loadImp (const ESM::ObjectState& state); diff --git a/apps/openmw/mwworld/ptr.cpp b/apps/openmw/mwworld/ptr.cpp deleted file mode 100644 index b18e3b1689..0000000000 --- a/apps/openmw/mwworld/ptr.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "ptr.hpp" - -#include - -#include "containerstore.hpp" -#include "class.hpp" -#include "livecellref.hpp" - -unsigned int MWWorld::Ptr::getType() const -{ - if(mRef != nullptr) - return mRef->mClass->getType(); - throw std::runtime_error("Can't get type name from an empty object."); -} - -MWWorld::LiveCellRefBase *MWWorld::Ptr::getBase() const -{ - if (!mRef) - throw std::runtime_error ("Can't access cell ref pointed to by null Ptr"); - - return mRef; -} - -MWWorld::CellRef& MWWorld::Ptr::getCellRef() const -{ - assert(mRef); - - return mRef->mRef; -} - -MWWorld::RefData& MWWorld::Ptr::getRefData() const -{ - assert(mRef); - - return mRef->mData; -} - -void MWWorld::Ptr::setContainerStore (ContainerStore *store) -{ - assert (store); - assert (!mCell); - - mContainerStore = store; -} - -MWWorld::ContainerStore *MWWorld::Ptr::getContainerStore() const -{ - return mContainerStore; -} - -MWWorld::Ptr::operator const void *() -{ - return mRef; -} - -// ------------------------------------------------------------------------------- - -unsigned int MWWorld::ConstPtr::getType() const -{ - if(mRef != nullptr) - return mRef->mClass->getType(); - throw std::runtime_error("Can't get type name from an empty object."); -} - -const MWWorld::LiveCellRefBase *MWWorld::ConstPtr::getBase() const -{ - if (!mRef) - throw std::runtime_error ("Can't access cell ref pointed to by null Ptr"); - - return mRef; -} - -void MWWorld::ConstPtr::setContainerStore (const ContainerStore *store) -{ - assert (store); - assert (!mCell); - - mContainerStore = store; -} - -const MWWorld::ContainerStore *MWWorld::ConstPtr::getContainerStore() const -{ - return mContainerStore; -} - -MWWorld::ConstPtr::operator const void *() -{ - return mRef; -} diff --git a/apps/openmw/mwworld/ptr.hpp b/apps/openmw/mwworld/ptr.hpp index a82abaa212..438b87c7af 100644 --- a/apps/openmw/mwworld/ptr.hpp +++ b/apps/openmw/mwworld/ptr.hpp @@ -2,7 +2,7 @@ #define GAME_MWWORLD_PTR_H #include - +#include #include #include @@ -15,20 +15,19 @@ namespace MWWorld struct LiveCellRefBase; /// \brief Pointer to a LiveCellRef - - class Ptr + /// @note PtrBase is never used directly and needed only to define Ptr and ConstPtr + template class TypeTransform> + class PtrBase { public: - MWWorld::LiveCellRefBase *mRef; - CellStore *mCell; - ContainerStore *mContainerStore; + typedef TypeTransform LiveCellRefBaseType; + typedef TypeTransform CellStoreType; + typedef TypeTransform ContainerStoreType; - public: - Ptr(MWWorld::LiveCellRefBase *liveCellRef=nullptr, CellStore *cell=nullptr) - : mRef(liveCellRef), mCell(cell), mContainerStore(nullptr) - { - } + LiveCellRefBaseType *mRef; + CellStoreType *mCell; + ContainerStoreType *mContainerStore; bool isEmpty() const { @@ -40,7 +39,12 @@ namespace MWWorld // Note 1: ids are not sequential. E.g. for a creature `getType` returns 0x41455243. // Note 2: Life is not easy and full of surprises. For example // prison marker reuses ESM::Door record. Player is ESM::NPC. - unsigned int getType() const; + unsigned int getType() const + { + if(mRef != nullptr) + return mRef->getType(); + throw std::runtime_error("Can't get type name from an empty object."); + } std::string_view getTypeDescription() const { @@ -55,9 +59,9 @@ namespace MWWorld } template - MWWorld::LiveCellRef *get() const + TypeTransform> *get() const { - MWWorld::LiveCellRef *ref = dynamic_cast*>(mRef); + TypeTransform> *ref = dynamic_cast>*>(mRef); if(ref) return ref; std::stringstream str; @@ -68,13 +72,26 @@ namespace MWWorld throw std::runtime_error(str.str()); } - MWWorld::LiveCellRefBase *getBase() const; + LiveCellRefBaseType *getBase() const + { + if (!mRef) + throw std::runtime_error ("Can't access cell ref pointed to by null Ptr"); + return mRef; + } - MWWorld::CellRef& getCellRef() const; + TypeTransform& getCellRef() const + { + assert(mRef); + return mRef->mRef; + } - RefData& getRefData() const; + TypeTransform& getRefData() const + { + assert(mRef); + return mRef->mData; + } - CellStore *getCell() const + CellStoreType *getCell() const { assert(mCell); return mCell; @@ -85,164 +102,47 @@ namespace MWWorld return (mContainerStore == nullptr) && (mCell != nullptr); } - void setContainerStore (ContainerStore *store); + void setContainerStore (ContainerStoreType *store) ///< Must not be called on references that are in a cell. + { + assert (store); + assert (!mCell); + mContainerStore = store; + } - ContainerStore *getContainerStore() const; + ContainerStoreType *getContainerStore() const ///< May return a 0-pointer, if reference is not in a container. + { + return mContainerStore; + } - operator const void *(); + operator const void *() const ///< Return a 0-pointer, if Ptr is empty; return a non-0-pointer, if Ptr is not empty + { + return mRef; + } + + protected: + PtrBase(LiveCellRefBaseType *liveCellRef, CellStoreType *cell, ContainerStoreType* containerStore) : mRef(liveCellRef), mCell(cell), mContainerStore(containerStore) {} }; - /// \brief Pointer to a const LiveCellRef + /// @note It is possible to get mutable values from const Ptr. So if a function accepts const Ptr&, the object is still mutable. + /// To make it really const the argument should be const ConstPtr&. + class Ptr : public PtrBase + { + public: + Ptr(LiveCellRefBase *liveCellRef=nullptr, CellStoreType *cell=nullptr) : PtrBase(liveCellRef, cell, nullptr) {} + }; + + /// @note The difference between Ptr and ConstPtr is that the second one adds const to the underlying pointers. /// @note a Ptr can be implicitely converted to a ConstPtr, but you can not convert a ConstPtr to a Ptr. - class ConstPtr + class ConstPtr : public PtrBase { public: - - const MWWorld::LiveCellRefBase *mRef; - const CellStore *mCell; - const ContainerStore *mContainerStore; - - public: - ConstPtr(const MWWorld::LiveCellRefBase *liveCellRef=nullptr, const CellStore *cell=nullptr) - : mRef(liveCellRef), mCell(cell), mContainerStore(nullptr) - { - } - - ConstPtr(const MWWorld::Ptr& ptr) - : mRef(ptr.mRef), mCell(ptr.mCell), mContainerStore(ptr.mContainerStore) - { - } - - bool isEmpty() const - { - return mRef == nullptr; - } - - unsigned int getType() const; - - std::string_view getTypeDescription() const - { - return mRef ? mRef->getTypeDescription() : "nullptr"; - } - - const Class& getClass() const - { - if(mRef != nullptr) - return *(mRef->mClass); - throw std::runtime_error("Cannot get class of an empty object"); - } - - template - const MWWorld::LiveCellRef *get() const - { - const MWWorld::LiveCellRef *ref = dynamic_cast*>(mRef); - if(ref) return ref; - - std::stringstream str; - str<< "Bad LiveCellRef cast to "<mRef; - } - - const RefData& getRefData() const - { - assert(mRef); - return mRef->mData; - } - - const CellStore *getCell() const - { - assert(mCell); - return mCell; - } - - bool isInCell() const - { - return (mContainerStore == nullptr) && (mCell != nullptr); - } - - void setContainerStore (const ContainerStore *store); - ///< Must not be called on references that are in a cell. - - const ContainerStore *getContainerStore() const; - ///< May return a 0-pointer, if reference is not in a container. - - operator const void *(); - ///< Return a 0-pointer, if Ptr is empty; return a non-0-pointer, if Ptr is not empty + ConstPtr(const Ptr& ptr) : PtrBase(ptr.mRef, ptr.mCell, ptr.mContainerStore) {} + ConstPtr(const LiveCellRefBase *liveCellRef=nullptr, const CellStoreType *cell=nullptr) : PtrBase(liveCellRef, cell, nullptr) {} }; - inline bool operator== (const Ptr& left, const Ptr& right) - { - return left.mRef==right.mRef; - } - - inline bool operator!= (const Ptr& left, const Ptr& right) - { - return !(left==right); - } - - inline bool operator< (const Ptr& left, const Ptr& right) - { - return left.mRef= (const Ptr& left, const Ptr& right) - { - return !(left (const Ptr& left, const Ptr& right) - { - return rightright); - } - - inline bool operator== (const ConstPtr& left, const ConstPtr& right) - { - return left.mRef==right.mRef; - } - - inline bool operator!= (const ConstPtr& left, const ConstPtr& right) - { - return !(left==right); - } - - inline bool operator< (const ConstPtr& left, const ConstPtr& right) - { - return left.mRef= (const ConstPtr& left, const ConstPtr& right) - { - return !(left (const ConstPtr& left, const ConstPtr& right) - { - return rightright); - } } #endif