From d7785a6da0a5ced69203270a48a9a4da9e8f230a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 2 Jun 2022 12:42:24 -0600 Subject: [PATCH] [cplusplus] Add unique_ptr --- src/hb-algs.hh | 5 +++++ src/hb-cplusplus.hh | 44 +++++++++++++++++++++++++++++++++++++- test/api/test-cplusplus.cc | 2 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 34e512e7e..ce4849b01 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -247,6 +247,11 @@ struct { return v.get () ? v.get ()->hash () : 0; } + template constexpr uint32_t + impl (const hb::unique_ptr& v, hb_priority<1>) const + { + return v.get () ? v.get ()->hash () : 0; + } template constexpr auto impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash>{} (hb_deref (v))) diff --git a/src/hb-cplusplus.hh b/src/hb-cplusplus.hh index 76122523e..86d045208 100644 --- a/src/hb-cplusplus.hh +++ b/src/hb-cplusplus.hh @@ -58,7 +58,7 @@ struct shared_ptr shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {} shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; } shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; } - shared_ptr& operator = (shared_ptr &&o) { destroy (); p = o.p; o.p = nullptr; return *this; } + shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } ~shared_ptr () { v::destroy (p); p = nullptr; } T* get() const { return p; } @@ -89,6 +89,38 @@ struct shared_ptr template struct is_shared_ptr : std::false_type {}; template struct is_shared_ptr> : std::true_type {}; +template +struct unique_ptr +{ + using element_type = T; + + using v = vtable; + + explicit unique_ptr (T *p = nullptr) : p (p) {} + unique_ptr (const unique_ptr &o) = delete; + unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; } + unique_ptr& operator = (const unique_ptr &o) = delete; + unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; } + ~unique_ptr () { v::destroy (p); p = nullptr; } + + T* get() const { return p; } + T* release () { T* v = p; p = nullptr; return v; } + + void swap (unique_ptr &o) { std::swap (p, o.p); } + friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); } + + operator T * () const { return p; } + T& operator * () const { return *get (); } + T* operator -> () const { return get (); } + operator bool () { return p; } + + private: + T *p; +}; + +template struct is_unique_ptr : std::false_type {}; +template struct is_unique_ptr> : std::true_type {}; + template > } }; +template +struct std::hash> +{ + std::size_t operator()(const hb::unique_ptr& v) const noexcept + { + std::size_t h = std::hash{}(v.get ()); + return h; + } +}; + #endif /* __cplusplus */ diff --git a/test/api/test-cplusplus.cc b/test/api/test-cplusplus.cc index d23e794c4..d742750f6 100644 --- a/test/api/test-cplusplus.cc +++ b/test/api/test-cplusplus.cc @@ -106,5 +106,7 @@ main () pb.set_user_data (&key, b, nullptr, true); (void) pb.get_user_data (&key); + hb::unique_ptr pb5 {pb3.reference ()}; + return pb == pb.get_empty () || pb == pb2; }