libcxx

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

move_convert.single.pass.cpp (7114B)


      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 
     11 // <memory>
     12 
     13 // unique_ptr
     14 
     15 // Test unique_ptr converting move ctor
     16 
     17 // NOTE: unique_ptr does not provide converting constructors in C++03
     18 // UNSUPPORTED: c++98, c++03
     19 
     20 #include <memory>
     21 #include <type_traits>
     22 #include <utility>
     23 #include <cassert>
     24 
     25 #include "test_macros.h"
     26 #include "unique_ptr_test_helper.h"
     27 
     28 // test converting move ctor.  Should only require a MoveConstructible deleter, or if
     29 //    deleter is a reference, not even that.
     30 // Explicit version
     31 
     32 template <class LHS, class RHS>
     33 void checkReferenceDeleter(LHS& lhs, RHS& rhs) {
     34   typedef typename LHS::deleter_type NewDel;
     35   static_assert(std::is_reference<NewDel>::value, "");
     36   rhs.get_deleter().set_state(42);
     37   assert(rhs.get_deleter().state() == 42);
     38   assert(lhs.get_deleter().state() == 42);
     39   lhs.get_deleter().set_state(99);
     40   assert(lhs.get_deleter().state() == 99);
     41   assert(rhs.get_deleter().state() == 99);
     42 }
     43 
     44 template <class LHS, class RHS>
     45 void checkDeleter(LHS& lhs, RHS& rhs, int LHSVal, int RHSVal) {
     46   assert(lhs.get_deleter().state() == LHSVal);
     47   assert(rhs.get_deleter().state() == RHSVal);
     48 }
     49 
     50 template <class LHS, class RHS>
     51 void checkCtor(LHS& lhs, RHS& rhs, A* RHSVal) {
     52   assert(lhs.get() == RHSVal);
     53   assert(rhs.get() == nullptr);
     54   assert(A::count == 1);
     55   assert(B::count == 1);
     56 }
     57 
     58 void checkNoneAlive() {
     59   assert(A::count == 0);
     60   assert(B::count == 0);
     61 }
     62 
     63 template <class T>
     64 struct NCConvertingDeleter {
     65   NCConvertingDeleter() = default;
     66   NCConvertingDeleter(NCConvertingDeleter const&) = delete;
     67   NCConvertingDeleter(NCConvertingDeleter&&) = default;
     68 
     69   template <class U>
     70   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
     71 
     72   void operator()(T*) const {}
     73 };
     74 
     75 template <class T>
     76 struct NCConvertingDeleter<T[]> {
     77   NCConvertingDeleter() = default;
     78   NCConvertingDeleter(NCConvertingDeleter const&) = delete;
     79   NCConvertingDeleter(NCConvertingDeleter&&) = default;
     80 
     81   template <class U>
     82   NCConvertingDeleter(NCConvertingDeleter<U>&&) {}
     83 
     84   void operator()(T*) const {}
     85 };
     86 
     87 struct NCGenericDeleter {
     88   NCGenericDeleter() = default;
     89   NCGenericDeleter(NCGenericDeleter const&) = delete;
     90   NCGenericDeleter(NCGenericDeleter&&) = default;
     91 
     92   void operator()(void*) const {}
     93 };
     94 
     95 void test_sfinae() {
     96   using DA = NCConvertingDeleter<A>; // non-copyable deleters
     97   using DB = NCConvertingDeleter<B>;
     98   using UA = std::unique_ptr<A>;
     99   using UB = std::unique_ptr<B>;
    100   using UAD = std::unique_ptr<A, DA>;
    101   using UBD = std::unique_ptr<B, DB>;
    102   { // cannot move from an lvalue
    103     static_assert(std::is_constructible<UA, UB&&>::value, "");
    104     static_assert(!std::is_constructible<UA, UB&>::value, "");
    105     static_assert(!std::is_constructible<UA, const UB&>::value, "");
    106   }
    107   { // cannot move if the deleter-types cannot convert
    108     static_assert(std::is_constructible<UAD, UBD&&>::value, "");
    109     static_assert(!std::is_constructible<UAD, UB&&>::value, "");
    110     static_assert(!std::is_constructible<UA, UBD&&>::value, "");
    111   }
    112   { // cannot move-convert with reference deleters of different types
    113     using UA1 = std::unique_ptr<A, DA&>;
    114     using UB1 = std::unique_ptr<B, DB&>;
    115     static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
    116   }
    117   { // cannot move-convert with reference deleters of different types
    118     using UA1 = std::unique_ptr<A, const DA&>;
    119     using UB1 = std::unique_ptr<B, const DB&>;
    120     static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
    121   }
    122   { // cannot move-convert from unique_ptr<Array[]>
    123     using UA1 = std::unique_ptr<A>;
    124     using UA2 = std::unique_ptr<A[]>;
    125     using UB1 = std::unique_ptr<B[]>;
    126     static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
    127     static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
    128   }
    129   { // cannot move-convert from unique_ptr<Array[]>
    130     using UA1 = std::unique_ptr<A, NCGenericDeleter>;
    131     using UA2 = std::unique_ptr<A[], NCGenericDeleter>;
    132     using UB1 = std::unique_ptr<B[], NCGenericDeleter>;
    133     static_assert(!std::is_constructible<UA1, UA2&&>::value, "");
    134     static_assert(!std::is_constructible<UA1, UB1&&>::value, "");
    135   }
    136 }
    137 
    138 void test_noexcept() {
    139   {
    140     typedef std::unique_ptr<A> APtr;
    141     typedef std::unique_ptr<B> BPtr;
    142     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    143   }
    144   {
    145     typedef std::unique_ptr<A, Deleter<A> > APtr;
    146     typedef std::unique_ptr<B, Deleter<B> > BPtr;
    147     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    148   }
    149   {
    150     typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
    151     typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
    152     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    153   }
    154   {
    155     typedef std::unique_ptr<A, const NCConstDeleter<A>&> APtr;
    156     typedef std::unique_ptr<B, const NCConstDeleter<A>&> BPtr;
    157     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    158   }
    159 }
    160 
    161 int main() {
    162   {
    163     test_sfinae();
    164     test_noexcept();
    165   }
    166   {
    167     typedef std::unique_ptr<A> APtr;
    168     typedef std::unique_ptr<B> BPtr;
    169     { // explicit
    170       BPtr b(new B);
    171       A* p = b.get();
    172       APtr a(std::move(b));
    173       checkCtor(a, b, p);
    174     }
    175     checkNoneAlive();
    176     { // implicit
    177       BPtr b(new B);
    178       A* p = b.get();
    179       APtr a = std::move(b);
    180       checkCtor(a, b, p);
    181     }
    182     checkNoneAlive();
    183   }
    184   { // test with moveable deleters
    185     typedef std::unique_ptr<A, Deleter<A> > APtr;
    186     typedef std::unique_ptr<B, Deleter<B> > BPtr;
    187     {
    188       Deleter<B> del(5);
    189       BPtr b(new B, std::move(del));
    190       A* p = b.get();
    191       APtr a(std::move(b));
    192       checkCtor(a, b, p);
    193       checkDeleter(a, b, 5, 0);
    194     }
    195     checkNoneAlive();
    196     {
    197       Deleter<B> del(5);
    198       BPtr b(new B, std::move(del));
    199       A* p = b.get();
    200       APtr a = std::move(b);
    201       checkCtor(a, b, p);
    202       checkDeleter(a, b, 5, 0);
    203     }
    204     checkNoneAlive();
    205   }
    206   { // test with reference deleters
    207     typedef std::unique_ptr<A, NCDeleter<A>&> APtr;
    208     typedef std::unique_ptr<B, NCDeleter<A>&> BPtr;
    209     NCDeleter<A> del(5);
    210     {
    211       BPtr b(new B, del);
    212       A* p = b.get();
    213       APtr a(std::move(b));
    214       checkCtor(a, b, p);
    215       checkReferenceDeleter(a, b);
    216     }
    217     checkNoneAlive();
    218     {
    219       BPtr b(new B, del);
    220       A* p = b.get();
    221       APtr a = std::move(b);
    222       checkCtor(a, b, p);
    223       checkReferenceDeleter(a, b);
    224     }
    225     checkNoneAlive();
    226   }
    227   {
    228     typedef std::unique_ptr<A, CDeleter<A> > APtr;
    229     typedef std::unique_ptr<B, CDeleter<B>&> BPtr;
    230     CDeleter<B> del(5);
    231     {
    232       BPtr b(new B, del);
    233       A* p = b.get();
    234       APtr a(std::move(b));
    235       checkCtor(a, b, p);
    236       checkDeleter(a, b, 5, 5);
    237     }
    238     checkNoneAlive();
    239     {
    240       BPtr b(new B, del);
    241       A* p = b.get();
    242       APtr a = std::move(b);
    243       checkCtor(a, b, p);
    244       checkDeleter(a, b, 5, 5);
    245     }
    246     checkNoneAlive();
    247   }
    248 }