blob: 1c99feaa6e103d38005e2c4f3ecd4d5f4e736793 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <memory>
// unique_ptr
// Example move-only deleter
#ifndef SUPPORT_DELETER_TYPES_H
#define SUPPORT_DELETER_TYPES_H
#include <type_traits>
#include <utility>
#include <cassert>
#include "test_macros.h"
#include "min_allocator.h"
#if TEST_STD_VER >= 11
template <class T>
class Deleter
{
int state_;
Deleter(const Deleter&);
Deleter& operator=(const Deleter&);
public:
Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
Deleter& operator=(Deleter&& r)
{
state_ = r.state_;
r.state_ = 0;
return *this;
}
Deleter() : state_(0) {}
explicit Deleter(int s) : state_(s) {}
~Deleter() {assert(state_ >= 0); state_ = -1;}
template <class U>
Deleter(Deleter<U>&& d,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
: state_(d.state()) {d.set_state(0);}
private:
template <class U>
Deleter(const Deleter<U>& d,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
public:
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete p;}
};
template <class T>
class Deleter<T[]>
{
int state_;
Deleter(const Deleter&);
Deleter& operator=(const Deleter&);
public:
Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
Deleter& operator=(Deleter&& r)
{
state_ = r.state_;
r.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;}
};
#else // TEST_STD_VER < 11
template <class T>
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 <class U>
Deleter(Deleter<U> d,
typename std::enable_if<!std::is_same<U, T>::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 T>
class Deleter<T[]>
{
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 <class T>
void
swap(Deleter<T>& x, Deleter<T>& y)
{
Deleter<T> t(std::move(x));
x = std::move(y);
y = std::move(t);
}
template <class T>
class CDeleter
{
int state_;
public:
CDeleter() : state_(0) {}
explicit CDeleter(int s) : state_(s) {}
~CDeleter() {assert(state_ >= 0); state_ = -1;}
template <class U>
CDeleter(const CDeleter<U>& d)
: state_(d.state()) {}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete p;}
};
template <class T>
class CDeleter<T[]>
{
int state_;
public:
CDeleter() : state_(0) {}
explicit CDeleter(int s) : state_(s) {}
template <class U>
CDeleter(const CDeleter<U>& d)
: state_(d.state()) {}
~CDeleter() {assert(state_ >= 0); state_ = -1;}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete [] p;}
};
template <class T>
void
swap(CDeleter<T>& x, CDeleter<T>& y)
{
CDeleter<T> t(std::move(x));
x = std::move(y);
y = std::move(t);
}
// Non-copyable deleter
template <class T>
class NCDeleter
{
int state_;
NCDeleter(NCDeleter const&);
NCDeleter& operator=(NCDeleter const&);
public:
NCDeleter() : state_(0) {}
explicit NCDeleter(int s) : state_(s) {}
~NCDeleter() {assert(state_ >= 0); state_ = -1;}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete p;}
};
template <class T>
class NCDeleter<T[]>
{
int state_;
NCDeleter(NCDeleter const&);
NCDeleter& operator=(NCDeleter const&);
public:
NCDeleter() : state_(0) {}
explicit NCDeleter(int s) : state_(s) {}
~NCDeleter() {assert(state_ >= 0); state_ = -1;}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete [] p;}
};
// Non-copyable deleter
template <class T>
class NCConstDeleter
{
int state_;
NCConstDeleter(NCConstDeleter const&);
NCConstDeleter& operator=(NCConstDeleter const&);
public:
NCConstDeleter() : state_(0) {}
explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) const {delete p;}
};
template <class T>
class NCConstDeleter<T[]>
{
int state_;
NCConstDeleter(NCConstDeleter const&);
NCConstDeleter& operator=(NCConstDeleter const&);
public:
NCConstDeleter() : state_(0) {}
explicit NCConstDeleter(int s) : state_(s) {}
~NCConstDeleter() {assert(state_ >= 0); state_ = -1;}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) const {delete [] p;}
};
// Non-copyable deleter
template <class T>
class CopyDeleter
{
int state_;
public:
CopyDeleter() : state_(0) {}
explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
CopyDeleter& operator=(CopyDeleter const& other) {
state_ = other.state_;
return *this;
}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
void operator()(T* p) {delete p;}
};
template <class T>
class CopyDeleter<T[]>
{
int state_;
public:
CopyDeleter() : state_(0) {}
explicit CopyDeleter(int s) : state_(s) {}
~CopyDeleter() {assert(state_ >= 0); state_ = -1;}
CopyDeleter(CopyDeleter const& other) : state_(other.state_) {}
CopyDeleter& operator=(CopyDeleter const& other) {
state_ = other.state_;
return *this;
}
int state() const {return state_;}
void set_state(int i) {state_ = i;}
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 T>
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 <class T>
void
swap(test_deleter<T>& x, test_deleter<T>& y)
{
test_deleter<T> t(std::move(x));
x = std::move(y);
y = std::move(t);
}
#if TEST_STD_VER >= 11
template <class T, size_t ID = 0>
class PointerDeleter
{
PointerDeleter(const PointerDeleter&);
PointerDeleter& operator=(const PointerDeleter&);
public:
typedef min_pointer<T, std::integral_constant<size_t, ID>> pointer;
PointerDeleter() = default;
PointerDeleter(PointerDeleter&&) = default;
PointerDeleter& operator=(PointerDeleter&&) = default;
explicit PointerDeleter(int) {}
template <class U>
PointerDeleter(PointerDeleter<U, ID>&&,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
{}
void operator()(pointer p) { if (p) { delete std::addressof(*p); }}
private:
template <class U>
PointerDeleter(const PointerDeleter<U, ID>&,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
};
template <class T, size_t ID>
class PointerDeleter<T[], ID>
{
PointerDeleter(const PointerDeleter&);
PointerDeleter& operator=(const PointerDeleter&);
public:
typedef min_pointer<T, std::integral_constant<size_t, ID> > pointer;
PointerDeleter() = default;
PointerDeleter(PointerDeleter&&) = default;
PointerDeleter& operator=(PointerDeleter&&) = default;
explicit PointerDeleter(int) {}
template <class U>
PointerDeleter(PointerDeleter<U, ID>&&,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
{}
void operator()(pointer p) { if (p) { delete [] std::addressof(*p); }}
private:
template <class U>
PointerDeleter(const PointerDeleter<U, ID>&,
typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
};
#endif // TEST_STD_VER >= 11
#endif // SUPPORT_DELETER_TYPES_H