Home | History | Annotate | Download | only in unique.ptr.single.ctor
      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 // Test unique_ptr converting move ctor
     15 
     16 #include <memory>
     17 #include <cassert>
     18 
     19 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
     20 //    deleter is a reference, not even that.
     21 // Explicit version
     22 
     23 struct A
     24 {
     25     static int count;
     26     A() {++count;}
     27     A(const A&) {++count;}
     28     virtual ~A() {--count;}
     29 };
     30 
     31 int A::count = 0;
     32 
     33 struct B
     34     : public A
     35 {
     36     static int count;
     37     B() {++count;}
     38     B(const B&) {++count;}
     39     virtual ~B() {--count;}
     40 };
     41 
     42 int B::count = 0;
     43 
     44 template <class T>
     45 class Deleter
     46 {
     47     int state_;
     48 
     49 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     50     Deleter(const Deleter&);
     51     Deleter& operator=(const Deleter&);
     52 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     53     Deleter(Deleter&);
     54     Deleter& operator=(Deleter&);
     55 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     56 
     57 public:
     58 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     59     Deleter(Deleter&& r) : state_(r.state_) {r.state_ = 0;}
     60     Deleter& operator=(Deleter&& r)
     61     {
     62         state_ = r.state_;
     63         r.state_ = 0;
     64         return *this;
     65     }
     66 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     67     operator std::__rv<Deleter>() {return std::__rv<Deleter>(*this);}
     68     Deleter(std::__rv<Deleter> r) : state_(r->state_) {r->state_ = 0;}
     69     Deleter& operator=(std::__rv<Deleter> r)
     70     {
     71         state_ = r->state_;
     72         r->state_ = 0;
     73         return *this;
     74     }
     75 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     76 
     77     Deleter() : state_(5) {}
     78 
     79 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     80     template <class U>
     81         Deleter(Deleter<U>&& d,
     82             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
     83             : state_(d.state()) {d.set_state(0);}
     84 
     85 private:
     86     template <class U>
     87         Deleter(const Deleter<U>& d,
     88             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0);
     89 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     90     template <class U>
     91         Deleter(Deleter<U> d,
     92             typename std::enable_if<!std::is_same<U, T>::value>::type* = 0)
     93             : state_(d.state()) {}
     94 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     95 public:
     96     int state() const {return state_;}
     97     void set_state(int i) {state_ = i;}
     98 
     99     void operator()(T* p) {delete p;}
    100 };
    101 
    102 int main()
    103 {
    104     {
    105     const std::unique_ptr<B, Deleter<B> > s(new B);
    106     A* p = s.get();
    107     std::unique_ptr<A, Deleter<A> > s2(s);
    108     assert(s2.get() == p);
    109     assert(s.get() == 0);
    110     assert(A::count == 1);
    111     assert(B::count == 1);
    112     assert(s2.get_deleter().state() == 5);
    113     assert(s.get_deleter().state() == 0);
    114     }
    115     assert(A::count == 0);
    116     assert(B::count == 0);
    117 }
    118