//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // unique_ptr // Example move-only deleter #ifndef SUPPORT_DELETER_TYPES_H #define SUPPORT_DELETER_TYPES_H #include #include #include #include #include "test_macros.h" #include "min_allocator.h" #if TEST_STD_VER >= 11 template class Deleter { int state_; Deleter(const Deleter&); Deleter& operator=(const Deleter&); public: TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; } TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) { state_ = r.state_; r.state_ = 0; return *this; } TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~Deleter() { assert(state_ >= 0); state_ = -1; } template TEST_CONSTEXPR_CXX23 Deleter(Deleter&& d, typename std::enable_if::value>::type* = 0) : state_(d.state()) { d.set_state(0); } private: template Deleter(const Deleter& d, typename std::enable_if::value>::type* = 0); public: TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; } }; template class Deleter { int state_; Deleter(const Deleter&); Deleter& operator=(const Deleter&); public: TEST_CONSTEXPR_CXX23 Deleter(Deleter&& r) : state_(r.state_) { r.state_ = 0; } TEST_CONSTEXPR_CXX23 Deleter& operator=(Deleter&& r) { state_ = r.state_; r.state_ = 0; return *this; } TEST_CONSTEXPR_CXX23 Deleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit Deleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~Deleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; } }; #else // TEST_STD_VER < 11 template class Deleter { mutable int state_; public: Deleter() : state_(0) {} explicit Deleter(int s) : state_(s) {} Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; } Deleter& operator=(Deleter const& other) { state_ = other.state_; other.state_ = 0; return *this; } ~Deleter() { assert(state_ >= 0); state_ = -1; } template Deleter(Deleter d, typename std::enable_if::value>::type* = 0) : state_(d.state()) {} public: int state() const { return state_; } void set_state(int i) { state_ = i; } void operator()(T* p) { delete p; } }; template class Deleter { mutable int state_; public: Deleter(Deleter const& other) : state_(other.state_) { other.state_ = 0; } Deleter& operator=(Deleter const& other) { state_ = other.state_; other.state_ = 0; return *this; } Deleter() : state_(0) {} explicit Deleter(int s) : state_(s) {} ~Deleter() { assert(state_ >= 0); state_ = -1; } int state() const { return state_; } void set_state(int i) { state_ = i; } void operator()(T* p) { delete[] p; } }; #endif template TEST_CONSTEXPR_CXX23 void swap(Deleter& x, Deleter& y) { Deleter t(std::move(x)); x = std::move(y); y = std::move(t); } template class CDeleter { int state_; public: TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default; TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default; TEST_CONSTEXPR_CXX23 ~CDeleter() { assert(state_ >= 0); state_ = -1; } template TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter& d) : state_(d.state()) {} TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; } }; template class CDeleter { int state_; public: TEST_CONSTEXPR_CXX23 CDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit CDeleter(int s) : state_(s) {} template TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter& d) : state_(d.state()) {} TEST_CONSTEXPR_CXX23 CDeleter(const CDeleter&) = default; TEST_CONSTEXPR_CXX23 CDeleter& operator=(const CDeleter&) = default; TEST_CONSTEXPR_CXX23 ~CDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; } }; template TEST_CONSTEXPR_CXX23 void swap(CDeleter& x, CDeleter& y) { CDeleter t(std::move(x)); x = std::move(y); y = std::move(t); } // Non-copyable deleter template class NCDeleter { int state_; NCDeleter(NCDeleter const&); NCDeleter& operator=(NCDeleter const&); public: TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~NCDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; } }; template class NCDeleter { int state_; NCDeleter(NCDeleter const&); NCDeleter& operator=(NCDeleter const&); public: TEST_CONSTEXPR_CXX23 NCDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit NCDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~NCDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; } }; // Non-copyable deleter template class NCConstDeleter { int state_; NCConstDeleter(NCConstDeleter const&); NCConstDeleter& operator=(NCConstDeleter const&); public: TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~NCConstDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete p; } }; template class NCConstDeleter { int state_; NCConstDeleter(NCConstDeleter const&); NCConstDeleter& operator=(NCConstDeleter const&); public: TEST_CONSTEXPR_CXX23 NCConstDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit NCConstDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~NCConstDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) const { delete[] p; } }; // Non-copyable deleter template class CopyDeleter { int state_; public: TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~CopyDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {} TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) { state_ = other.state_; return *this; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; } }; template class CopyDeleter { int state_; public: TEST_CONSTEXPR_CXX23 CopyDeleter() : state_(0) {} TEST_CONSTEXPR_CXX23 explicit CopyDeleter(int s) : state_(s) {} TEST_CONSTEXPR_CXX23 ~CopyDeleter() { assert(state_ >= 0); state_ = -1; } TEST_CONSTEXPR_CXX23 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {} TEST_CONSTEXPR_CXX23 CopyDeleter& operator=(CopyDeleter const& other) { state_ = other.state_; return *this; } TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void set_state(int i) { state_ = i; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; } }; struct test_deleter_base { static int count; static int dealloc_count; }; int test_deleter_base::count = 0; int test_deleter_base::dealloc_count = 0; template class test_deleter : public test_deleter_base { int state_; public: test_deleter() : state_(0) { ++count; } explicit test_deleter(int s) : state_(s) { ++count; } test_deleter(const test_deleter& d) : state_(d.state_) { ++count; } ~test_deleter() { assert(state_ >= 0); --count; state_ = -1; } int state() const { return state_; } void set_state(int i) { state_ = i; } void operator()(T* p) { assert(state_ >= 0); ++dealloc_count; delete p; } #if TEST_STD_VER >= 11 test_deleter* operator&() const = delete; #else private: test_deleter* operator&() const; #endif }; template void swap(test_deleter& x, test_deleter& y) { test_deleter t(std::move(x)); x = std::move(y); y = std::move(t); } #if TEST_STD_VER >= 11 template class PointerDeleter { PointerDeleter(const PointerDeleter&); PointerDeleter& operator=(const PointerDeleter&); public: typedef min_pointer> pointer; TEST_CONSTEXPR_CXX23 PointerDeleter() = default; TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&) = default; TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default; TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {} template TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&, typename std::enable_if::value>::type* = 0) {} TEST_CONSTEXPR_CXX23 void operator()(pointer p) { if (p) { delete std::addressof(*p); } } private: template PointerDeleter(const PointerDeleter&, typename std::enable_if::value>::type* = 0); }; template class PointerDeleter { PointerDeleter(const PointerDeleter&); PointerDeleter& operator=(const PointerDeleter&); public: typedef min_pointer > pointer; TEST_CONSTEXPR_CXX23 PointerDeleter() = default; TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&) = default; TEST_CONSTEXPR_CXX23 PointerDeleter& operator=(PointerDeleter&&) = default; TEST_CONSTEXPR_CXX23 explicit PointerDeleter(int) {} template TEST_CONSTEXPR_CXX23 PointerDeleter(PointerDeleter&&, typename std::enable_if::value>::type* = 0) {} TEST_CONSTEXPR_CXX23 void operator()(pointer p) { if (p) { delete[] std::addressof(*p); } } private: template PointerDeleter(const PointerDeleter&, typename std::enable_if::value>::type* = 0); }; #endif // TEST_STD_VER >= 11 template class DefaultCtorDeleter { int state_; public: TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete p; } }; template class DefaultCtorDeleter { int state_; public: TEST_CONSTEXPR_CXX23 int state() const { return state_; } TEST_CONSTEXPR_CXX23 void operator()(T* p) { delete[] p; } }; #endif // SUPPORT_DELETER_TYPES_H