// By Nicolaus Anderson, 2018 // Based on code posted by Ethon for free on Irrlicht // Thanks Ethon! #include #include #ifndef __IRRPTR_H__ #define __IRRPTR_H__ // Uncomment to enable //#define IRRPTR_CHECK_ACCESS #ifdef IRRPTR_CHECK_ACCESS class IrrPtrAccessNullException {}; #endif namespace irr { namespace tools { template class irrptr : std::enable_if< std::is_base_of< irr::IReferenceCounted, ObjectType >::value > { public: typedef typename std::remove_pointer< ObjectType >::type element_type; typedef element_type* pointer; typedef element_type const* const_pointer; irrptr() : dataptr(nullptr) {} irrptr( const irrptr& other ) : dataptr( other.dataptr ) { grab(); } irrptr& operator= ( irrptr& other ) { set(other.dataptr); return *this; } ~irrptr() { drop(); } void set( pointer data ) { if ( dataptr == data ) return; drop(); if ( data == 0 ) // Force nullptr usage dataptr = nullptr; else dataptr = data; grab(); } void share( irrptr& other ) { if ( dataptr == other.dataptr ) return; drop(); dataptr = other.dataptr; grab(); } void swap( irrptr& other ) { pointer p = other.dataptr; other.dataptr = dataptr; dataptr = p; } void dump() { drop(); } void quiet_dump() { // No drop dataptr = nullptr; } pointer get() { return dataptr; } const_pointer get() const { return dataptr; } element_type& access() { #ifdef IRRPTR_CHECK_ACCESS if ( !dataptr ) throw IrrPtrAccessNullException(); #endif return *dataptr; } element_type const& access() const { #ifdef IRRPTR_CHECK_ACCESS if ( !dataptr ) throw IrrPtrAccessNullException(); #endif return *dataptr; } explicit operator bool() const { return (dataptr != nullptr); } protected: void grab() { if ( dataptr ) dataptr->grab(); } void drop() { if ( dataptr ) dataptr->drop(); } private: pointer dataptr; }; }} namespace std { template void swap( ::irr::tools::irrptr& p1, ::irr::tools::irrptr& p2) { p1.swap(p2); } } #endif // _IRRPTR_HPP__