libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

move_convert.single.pass.cpp (4425B)


      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 // UNSUPPORTED: c++98, c++03
     11 
     12 // <memory>
     13 
     14 // unique_ptr
     15 
     16 // Test unique_ptr converting move assignment
     17 
     18 #include <memory>
     19 #include <utility>
     20 #include <cassert>
     21 
     22 #include "deleter_types.h"
     23 #include "unique_ptr_test_helper.h"
     24 
     25 template <class APtr, class BPtr>
     26 void testAssign(APtr& aptr, BPtr& bptr) {
     27   A* p = bptr.get();
     28   assert(A::count == 2);
     29   aptr = std::move(bptr);
     30   assert(aptr.get() == p);
     31   assert(bptr.get() == 0);
     32   assert(A::count == 1);
     33   assert(B::count == 1);
     34 }
     35 
     36 template <class LHS, class RHS>
     37 void checkDeleter(LHS& lhs, RHS& rhs, int LHSState, int RHSState) {
     38   assert(lhs.get_deleter().state() == LHSState);
     39   assert(rhs.get_deleter().state() == RHSState);
     40 }
     41 
     42 template <class T>
     43 struct NCConvertingDeleter {
     44   NCConvertingDeleter() = default;
     45   NCConvertingDeleter(NCConvertingDeleter const&) = delete;
     46   NCConvertingDeleter(NCConvertingDeleter&&) = default;
     47 
     48   template <class U>
     49   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
     50 
     51   void operator()(T*) const {}
     52 };
     53 
     54 template <class T>
     55 struct NCConvertingDeleter<T[]> {
     56   NCConvertingDeleter() = default;
     57   NCConvertingDeleter(NCConvertingDeleter const&) = delete;
     58   NCConvertingDeleter(NCConvertingDeleter&&) = default;
     59 
     60   template <class U>
     61   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
     62 
     63   void operator()(T*) const {}
     64 };
     65 
     66 struct NCGenericDeleter {
     67   NCGenericDeleter() = default;
     68   NCGenericDeleter(NCGenericDeleter const&) = delete;
     69   NCGenericDeleter(NCGenericDeleter&&) = default;
     70 
     71   void operator()(void*) const {}
     72 };
     73 
     74 void test_sfinae() {
     75   using DA = NCConvertingDeleter<A>; // non-copyable deleters
     76   using DB = NCConvertingDeleter<B>;
     77   using UA = std::unique_ptr<A>;
     78   using UB = std::unique_ptr<B>;
     79   using UAD = std::unique_ptr<A, DA>;
     80   using UBD = std::unique_ptr<B, DB>;
     81   { // cannot move from an lvalue
     82     static_assert(std::is_assignable<UA, UB&&>::value, "");
     83     static_assert(!std::is_assignable<UA, UB&>::value, "");
     84     static_assert(!std::is_assignable<UA, const UB&>::value, "");
     85   }
     86   { // cannot move if the deleter-types cannot convert
     87     static_assert(std::is_assignable<UAD, UBD&&>::value, "");
     88     static_assert(!std::is_assignable<UAD, UB&&>::value, "");
     89     static_assert(!std::is_assignable<UA, UBD&&>::value, "");
     90   }
     91   { // cannot move-convert with reference deleters of different types
     92     using UA1 = std::unique_ptr<A, DA&>;
     93     using UB1 = std::unique_ptr<B, DB&>;
     94     static_assert(!std::is_assignable<UA1, UB1&&>::value, "");
     95   }
     96   { // cannot move-convert with reference deleters of different types
     97     using UA1 = std::unique_ptr<A, const DA&>;
     98     using UB1 = std::unique_ptr<B, const DB&>;
     99     static_assert(!std::is_assignable<UA1, UB1&&>::value, "");
    100   }
    101   { // cannot move-convert from unique_ptr<Array[]>
    102     using UA1 = std::unique_ptr<A>;
    103     using UA2 = std::unique_ptr<A[]>;
    104     using UB1 = std::unique_ptr<B[]>;
    105     static_assert(!std::is_assignable<UA1, UA2&&>::value, "");
    106     static_assert(!std::is_assignable<UA1, UB1&&>::value, "");
    107   }
    108   { // cannot move-convert from unique_ptr<Array[]>
    109     using UA1 = std::unique_ptr<A, NCGenericDeleter>;
    110     using UA2 = std::unique_ptr<A[], NCGenericDeleter>;
    111     using UB1 = std::unique_ptr<B[], NCGenericDeleter>;
    112     static_assert(!std::is_assignable<UA1, UA2&&>::value, "");
    113     static_assert(!std::is_assignable<UA1, UB1&&>::value, "");
    114   }
    115 }
    116 
    117 int main() {
    118   test_sfinae();
    119   {
    120     std::unique_ptr<B> bptr(new B);
    121     std::unique_ptr<A> aptr(new A);
    122     testAssign(aptr, bptr);
    123   }
    124   assert(A::count == 0);
    125   assert(B::count == 0);
    126   {
    127     Deleter<B> del(42);
    128     std::unique_ptr<B, Deleter<B> > bptr(new B, std::move(del));
    129     std::unique_ptr<A, Deleter<A> > aptr(new A);
    130     testAssign(aptr, bptr);
    131     checkDeleter(aptr, bptr, 42, 0);
    132   }
    133   assert(A::count == 0);
    134   assert(B::count == 0);
    135   {
    136     CDeleter<A> adel(6);
    137     CDeleter<B> bdel(42);
    138     std::unique_ptr<B, CDeleter<B>&> bptr(new B, bdel);
    139     std::unique_ptr<A, CDeleter<A>&> aptr(new A, adel);
    140     testAssign(aptr, bptr);
    141     checkDeleter(aptr, bptr, 42, 42);
    142   }
    143   assert(A::count == 0);
    144   assert(B::count == 0);
    145 }