1//===----------------------------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// <memory> 11 12// unique_ptr 13 14// Example move-only deleter 15 16#ifndef SUPPORT_DELETER_TYPES_H 17#define SUPPORT_DELETER_TYPES_H 18 19#include <type_traits> 20#include <utility> 21#include <cassert> 22 23#include "test_macros.h" 24#include "min_allocator.h" 25 26#if TEST_STD_VER >= 11 27 28template <class T> 29class Deleter 30{ 31 int state_; 32 33 Deleter(const Deleter&); 34 Deleter& operator=(const Deleter&); 35 36public: 37 Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;} 38 Deleter& operator=(Deleter&& r) 39 { 40 state_ = r.state_; 41 r.state_ = 0; 42 return *this; 43 } 44 45 46 Deleter() : state_(0) {} 47 explicit Deleter(int s) : state_(s) {} 48 ~Deleter() {assert(state_ >= 0); state_ = -1;} 49 50 template <class U> 51 Deleter(Deleter<U>&& d, 52 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) 53 : state_(d.state()) {d.set_state(0);} 54 55private: 56 template <class U> 57 Deleter(const Deleter<U>& d, 58 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0); 59public: 60 int state() const {return state_;} 61 void set_state(int i) {state_ = i;} 62 63 void operator()(T* p) {delete p;} 64}; 65 66template <class T> 67class Deleter<T[]> 68{ 69 int state_; 70 71 Deleter(const Deleter&); 72 Deleter& operator=(const Deleter&); 73 74public: 75 76 Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;} 77 Deleter& operator=(Deleter&& r) 78 { 79 state_ = r.state_; 80 r.state_ = 0; 81 return *this; 82 } 83 84 Deleter() : state_(0) {} 85 explicit Deleter(int s) : state_(s) {} 86 ~Deleter() {assert(state_ >= 0); state_ = -1;} 87 88 int state() const {return state_;} 89 void set_state(int i) {state_ = i;} 90 91 void operator()(T* p) {delete [] p;} 92}; 93 94#else // TEST_STD_VER < 11 95 96template <class T> 97class Deleter 98{ 99 mutable int state_; 100 101public: 102 Deleter() : state_(0) {} 103 explicit Deleter(int s) : state_(s) {} 104 105 Deleter(Deleter const & other) : state_(other.state_) { 106 other.state_ = 0; 107 } 108 Deleter& operator=(Deleter const& other) { 109 state_ = other.state_; 110 other.state_ = 0; 111 return *this; 112 } 113 114 ~Deleter() {assert(state_ >= 0); state_ = -1;} 115 116 template <class U> 117 Deleter(Deleter<U> d, 118 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) 119 : state_(d.state()) {} 120 121public: 122 int state() const {return state_;} 123 void set_state(int i) {state_ = i;} 124 125 void operator()(T* p) {delete p;} 126}; 127 128template <class T> 129class Deleter<T[]> 130{ 131 mutable int state_; 132 133public: 134 135 Deleter(Deleter const& other) : state_(other.state_) { 136 other.state_ = 0; 137 } 138 Deleter& operator=(Deleter const& other) { 139 state_ = other.state_; 140 other.state_ = 0; 141 return *this; 142 } 143 144 Deleter() : state_(0) {} 145 explicit Deleter(int s) : state_(s) {} 146 ~Deleter() {assert(state_ >= 0); state_ = -1;} 147 148 int state() const {return state_;} 149 void set_state(int i) {state_ = i;} 150 151 void operator()(T* p) {delete [] p;} 152}; 153 154#endif 155 156template <class T> 157void 158swap(Deleter<T>& x, Deleter<T>& y) 159{ 160 Deleter<T> t(std::move(x)); 161 x = std::move(y); 162 y = std::move(t); 163} 164 165 166template <class T> 167class CDeleter 168{ 169 int state_; 170 171public: 172 173 CDeleter() : state_(0) {} 174 explicit CDeleter(int s) : state_(s) {} 175 ~CDeleter() {assert(state_ >= 0); state_ = -1;} 176 177 template <class U> 178 CDeleter(const CDeleter<U>& d) 179 : state_(d.state()) {} 180 181 int state() const {return state_;} 182 void set_state(int i) {state_ = i;} 183 184 void operator()(T* p) {delete p;} 185}; 186 187template <class T> 188class CDeleter<T[]> 189{ 190 int state_; 191 192public: 193 194 CDeleter() : state_(0) {} 195 explicit CDeleter(int s) : state_(s) {} 196 ~CDeleter() {assert(state_ >= 0); state_ = -1;} 197 198 int state() const {return state_;} 199 void set_state(int i) {state_ = i;} 200 201 void operator()(T* p) {delete [] p;} 202}; 203 204template <class T> 205void 206swap(CDeleter<T>& x, CDeleter<T>& y) 207{ 208 CDeleter<T> t(std::move(x)); 209 x = std::move(y); 210 y = std::move(t); 211} 212 213// Non-copyable deleter 214template <class T> 215class NCDeleter 216{ 217 int state_; 218 NCDeleter(NCDeleter const&); 219 NCDeleter& operator=(NCDeleter const&); 220public: 221 222 NCDeleter() : state_(0) {} 223 explicit NCDeleter(int s) : state_(s) {} 224 ~NCDeleter() {assert(state_ >= 0); state_ = -1;} 225 226 int state() const {return state_;} 227 void set_state(int i) {state_ = i;} 228 229 void operator()(T* p) {delete p;} 230}; 231 232 233template <class T> 234class NCDeleter<T[]> 235{ 236 int state_; 237 NCDeleter(NCDeleter const&); 238 NCDeleter& operator=(NCDeleter const&); 239public: 240 241 NCDeleter() : state_(0) {} 242 explicit NCDeleter(int s) : state_(s) {} 243 ~NCDeleter() {assert(state_ >= 0); state_ = -1;} 244 245 int state() const {return state_;} 246 void set_state(int i) {state_ = i;} 247 248 void operator()(T* p) {delete [] p;} 249}; 250 251 252// Non-copyable deleter 253template <class T> 254class NCConstDeleter 255{ 256 int state_; 257 NCConstDeleter(NCConstDeleter const&); 258 NCConstDeleter& operator=(NCConstDeleter const&); 259public: 260 261 NCConstDeleter() : state_(0) {} 262 explicit NCConstDeleter(int s) : state_(s) {} 263 ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;} 264 265 int state() const {return state_;} 266 void set_state(int i) {state_ = i;} 267 268 void operator()(T* p) const {delete p;} 269}; 270 271 272template <class T> 273class NCConstDeleter<T[]> 274{ 275 int state_; 276 NCConstDeleter(NCConstDeleter const&); 277 NCConstDeleter& operator=(NCConstDeleter const&); 278public: 279 280 NCConstDeleter() : state_(0) {} 281 explicit NCConstDeleter(int s) : state_(s) {} 282 ~NCConstDeleter() {assert(state_ >= 0); state_ = -1;} 283 284 int state() const {return state_;} 285 void set_state(int i) {state_ = i;} 286 287 void operator()(T* p) const {delete [] p;} 288}; 289 290 291// Non-copyable deleter 292template <class T> 293class CopyDeleter 294{ 295 int state_; 296public: 297 298 CopyDeleter() : state_(0) {} 299 explicit CopyDeleter(int s) : state_(s) {} 300 ~CopyDeleter() {assert(state_ >= 0); state_ = -1;} 301 302 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {} 303 CopyDeleter& operator=(CopyDeleter const& other) { 304 state_ = other.state_; 305 return *this; 306 } 307 308 int state() const {return state_;} 309 void set_state(int i) {state_ = i;} 310 311 void operator()(T* p) {delete p;} 312}; 313 314 315template <class T> 316class CopyDeleter<T[]> 317{ 318 int state_; 319 320public: 321 322 CopyDeleter() : state_(0) {} 323 explicit CopyDeleter(int s) : state_(s) {} 324 ~CopyDeleter() {assert(state_ >= 0); state_ = -1;} 325 326 CopyDeleter(CopyDeleter const& other) : state_(other.state_) {} 327 CopyDeleter& operator=(CopyDeleter const& other) { 328 state_ = other.state_; 329 return *this; 330 } 331 332 int state() const {return state_;} 333 void set_state(int i) {state_ = i;} 334 335 void operator()(T* p) {delete [] p;} 336}; 337 338 339struct test_deleter_base 340{ 341 static int count; 342 static int dealloc_count; 343}; 344 345int test_deleter_base::count = 0; 346int test_deleter_base::dealloc_count = 0; 347 348template <class T> 349class test_deleter 350 : public test_deleter_base 351{ 352 int state_; 353 354public: 355 356 test_deleter() : state_(0) {++count;} 357 explicit test_deleter(int s) : state_(s) {++count;} 358 test_deleter(const test_deleter& d) 359 : state_(d.state_) {++count;} 360 ~test_deleter() {assert(state_ >= 0); --count; state_ = -1;} 361 362 int state() const {return state_;} 363 void set_state(int i) {state_ = i;} 364 365 void operator()(T* p) {assert(state_ >= 0); ++dealloc_count; delete p;} 366#if TEST_STD_VER >= 11 367 test_deleter* operator&() const = delete; 368#else 369private: 370 test_deleter* operator&() const; 371#endif 372}; 373 374template <class T> 375void 376swap(test_deleter<T>& x, test_deleter<T>& y) 377{ 378 test_deleter<T> t(std::move(x)); 379 x = std::move(y); 380 y = std::move(t); 381} 382 383#if TEST_STD_VER >= 11 384 385template <class T, size_t ID = 0> 386class PointerDeleter 387{ 388 PointerDeleter(const PointerDeleter&); 389 PointerDeleter& operator=(const PointerDeleter&); 390 391public: 392 typedef min_pointer<T, std::integral_constant<size_t, ID>> pointer; 393 394 PointerDeleter() = default; 395 PointerDeleter(PointerDeleter&&) = default; 396 PointerDeleter& operator=(PointerDeleter&&) = default; 397 explicit PointerDeleter(int) {} 398 399 template <class U> 400 PointerDeleter(PointerDeleter<U, ID>&&, 401 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) 402 {} 403 404 void operator()(pointer p) { if (p) { delete std::addressof(*p); }} 405 406private: 407 template <class U> 408 PointerDeleter(const PointerDeleter<U, ID>&, 409 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0); 410}; 411 412 413template <class T, size_t ID> 414class PointerDeleter<T[], ID> 415{ 416 PointerDeleter(const PointerDeleter&); 417 PointerDeleter& operator=(const PointerDeleter&); 418 419public: 420 typedef min_pointer<T, std::integral_constant<size_t, ID> > pointer; 421 422 PointerDeleter() = default; 423 PointerDeleter(PointerDeleter&&) = default; 424 PointerDeleter& operator=(PointerDeleter&&) = default; 425 explicit PointerDeleter(int) {} 426 427 template <class U> 428 PointerDeleter(PointerDeleter<U, ID>&&, 429 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0) 430 {} 431 432 void operator()(pointer p) { if (p) { delete [] std::addressof(*p); }} 433 434private: 435 template <class U> 436 PointerDeleter(const PointerDeleter<U, ID>&, 437 typename std::enable_if<!std::is_same<U, T>::value>::type* = 0); 438}; 439 440#endif // TEST_STD_VER >= 11 441 442#endif // SUPPORT_DELETER_TYPES_H 443