irr_ptr: Allow to use with forward-declared types

Also add [[nodiscard]] to ::grab() (because similar named irr_ptr::grab() returns void).
And use new std::is_convertible_v.
This commit is contained in:
Desour 2023-07-10 00:00:00 +02:00 committed by sfan5
parent 70e169f165
commit 6d01ed5d74
2 changed files with 17 additions and 14 deletions

@ -20,8 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include "irrlichttypes.h" namespace irr { class IReferenceCounted; }
#include "IReferenceCounted.h"
/** Shared pointer for IrrLicht objects. /** Shared pointer for IrrLicht objects.
* *
@ -37,15 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* from such object is a bug and may lead to a crash. Indirect construction * from such object is a bug and may lead to a crash. Indirect construction
* is possible though; see the @c grab free function for details and use cases. * is possible though; see the @c grab free function for details and use cases.
*/ */
template <class ReferenceCounted, template <class ReferenceCounted>
class = typename std::enable_if<std::is_base_of<IReferenceCounted,
ReferenceCounted>::value>::type>
class irr_ptr class irr_ptr
{ {
ReferenceCounted *value = nullptr; ReferenceCounted *value = nullptr;
public: public:
irr_ptr() {} irr_ptr() noexcept = default;
irr_ptr(std::nullptr_t) noexcept {} irr_ptr(std::nullptr_t) noexcept {}
@ -53,15 +50,15 @@ public:
irr_ptr(irr_ptr &&b) noexcept { reset(b.release()); } irr_ptr(irr_ptr &&b) noexcept { reset(b.release()); }
template <typename B, class = typename std::enable_if<std::is_convertible<B *, template <typename B,
ReferenceCounted *>::value>::type> std::enable_if_t<std::is_convertible_v<B *, ReferenceCounted *>, bool> = true>
irr_ptr(const irr_ptr<B> &b) noexcept irr_ptr(const irr_ptr<B> &b) noexcept
{ {
grab(b.get()); grab(b.get());
} }
template <typename B, class = typename std::enable_if<std::is_convertible<B *, template <typename B,
ReferenceCounted *>::value>::type> std::enable_if_t<std::is_convertible_v<B *, ReferenceCounted *>, bool> = true>
irr_ptr(irr_ptr<B> &&b) noexcept irr_ptr(irr_ptr<B> &&b) noexcept
{ {
reset(b.release()); reset(b.release());
@ -88,16 +85,16 @@ public:
return *this; return *this;
} }
template <typename B, class = typename std::enable_if<std::is_convertible<B *, template <typename B,
ReferenceCounted *>::value>::type> std::enable_if_t<std::is_convertible_v<B *, ReferenceCounted *>, bool> = true>
irr_ptr &operator=(const irr_ptr<B> &b) noexcept irr_ptr &operator=(const irr_ptr<B> &b) noexcept
{ {
grab(b.get()); grab(b.get());
return *this; return *this;
} }
template <typename B, class = typename std::enable_if<std::is_convertible<B *, template <typename B,
ReferenceCounted *>::value>::type> std::enable_if_t<std::is_convertible_v<B *, ReferenceCounted *>, bool> = true>
irr_ptr &operator=(irr_ptr<B> &&b) noexcept irr_ptr &operator=(irr_ptr<B> &&b) noexcept
{ {
reset(b.release()); reset(b.release());
@ -128,6 +125,8 @@ public:
*/ */
void reset(ReferenceCounted *object = nullptr) noexcept void reset(ReferenceCounted *object = nullptr) noexcept
{ {
static_assert(std::is_base_of_v<irr::IReferenceCounted, ReferenceCounted>,
"Class is not an IReferenceCounted");
if (value) if (value)
value->drop(); value->drop();
value = object; value = object;
@ -138,6 +137,8 @@ public:
*/ */
void grab(ReferenceCounted *object) noexcept void grab(ReferenceCounted *object) noexcept
{ {
static_assert(std::is_base_of_v<irr::IReferenceCounted, ReferenceCounted>,
"Class is not an IReferenceCounted");
if (object) if (object)
object->grab(); object->grab();
reset(object); reset(object);
@ -152,6 +153,7 @@ public:
* in this function and decreased when the returned pointer is destroyed. * in this function and decreased when the returned pointer is destroyed.
*/ */
template <class ReferenceCounted> template <class ReferenceCounted>
[[nodiscard]]
irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept
{ {
irr_ptr<ReferenceCounted> ptr; irr_ptr<ReferenceCounted> ptr;

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "exceptions.h" #include "exceptions.h"
#include "irr_ptr.h" #include "irr_ptr.h"
#include "IReferenceCounted.h"
class TestIrrPtr : public TestBase class TestIrrPtr : public TestBase
{ {