Home | History | Annotate | Download | only in unique.ptr.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 //=============================================================================
     15 // TESTING unique_ptr(pointer, deleter)
     16 //
     17 // Concerns:
     18 //   1 unique_ptr(pointer, deleter&&) only requires a MoveConstructible deleter.
     19 //   2 unique_ptr(pointer, deleter&) requires a CopyConstructible deleter.
     20 //   3 unique_ptr<T, D&>(pointer, deleter) does not require a CopyConstructible deleter.
     21 //   4 unique_ptr<T, D const&>(pointer, deleter) does not require a CopyConstructible deleter.
     22 //   5 unique_ptr(pointer, deleter) should work for derived pointers.
     23 //   6 unique_ptr(pointer, deleter) should work with function pointers.
     24 //   7 unique_ptr<void> should work.
     25 
     26 #include <memory>
     27 #include <cassert>
     28 
     29 #include "test_macros.h"
     30 #include "unique_ptr_test_helper.h"
     31 
     32 bool my_free_called = false;
     33 
     34 void my_free(void*) { my_free_called = true; }
     35 
     36 #if TEST_STD_VER >= 11
     37 struct DeleterBase {
     38   void operator()(void*) const {}
     39 };
     40 struct CopyOnlyDeleter : DeleterBase {
     41   CopyOnlyDeleter() = default;
     42   CopyOnlyDeleter(CopyOnlyDeleter const&) = default;
     43   CopyOnlyDeleter(CopyOnlyDeleter&&) = delete;
     44 };
     45 struct MoveOnlyDeleter : DeleterBase {
     46   MoveOnlyDeleter() = default;
     47   MoveOnlyDeleter(MoveOnlyDeleter&&) = default;
     48 };
     49 struct NoCopyMoveDeleter : DeleterBase {
     50   NoCopyMoveDeleter() = default;
     51   NoCopyMoveDeleter(NoCopyMoveDeleter const&) = delete;
     52 };
     53 #endif
     54 
     55 template <bool IsArray>
     56 void test_sfinae() {
     57 #if TEST_STD_VER >= 11
     58   typedef typename std::conditional<!IsArray, int, int[]>::type VT;
     59   {
     60     using D = CopyOnlyDeleter;
     61     using U = std::unique_ptr<VT, D>;
     62     static_assert(std::is_constructible<U, int*, D const&>::value, "");
     63     static_assert(std::is_constructible<U, int*, D&>::value, "");
     64     static_assert(std::is_constructible<U, int*, D&&>::value, "");
     65     // FIXME: __libcpp_compressed_pair attempts to perform a move even though
     66     // it should only copy.
     67     //D d;
     68     //U u(nullptr, std::move(d));
     69   }
     70   {
     71     using D = MoveOnlyDeleter;
     72     using U = std::unique_ptr<VT, D>;
     73     static_assert(!std::is_constructible<U, int*, D const&>::value, "");
     74     static_assert(!std::is_constructible<U, int*, D&>::value, "");
     75     static_assert(std::is_constructible<U, int*, D&&>::value, "");
     76     D d;
     77     U u(nullptr, std::move(d));
     78   }
     79   {
     80     using D = NoCopyMoveDeleter;
     81     using U = std::unique_ptr<VT, D>;
     82     static_assert(!std::is_constructible<U, int*, D const&>::value, "");
     83     static_assert(!std::is_constructible<U, int*, D&>::value, "");
     84     static_assert(!std::is_constructible<U, int*, D&&>::value, "");
     85   }
     86   {
     87     using D = NoCopyMoveDeleter;
     88     using U = std::unique_ptr<VT, D&>;
     89     static_assert(!std::is_constructible<U, int*, D const&>::value, "");
     90     static_assert(std::is_constructible<U, int*, D&>::value, "");
     91     static_assert(!std::is_constructible<U, int*, D&&>::value, "");
     92     static_assert(!std::is_constructible<U, int*, const D&&>::value, "");
     93   }
     94   {
     95     using D = NoCopyMoveDeleter;
     96     using U = std::unique_ptr<VT, const D&>;
     97     static_assert(std::is_constructible<U, int*, D const&>::value, "");
     98     static_assert(std::is_constructible<U, int*, D&>::value, "");
     99     static_assert(!std::is_constructible<U, int*, D&&>::value, "");
    100     static_assert(!std::is_constructible<U, int*, const D&&>::value, "");
    101   }
    102 #endif
    103 }
    104 
    105 template <bool IsArray>
    106 void test_noexcept() {
    107 #if TEST_STD_VER >= 11
    108   typedef typename std::conditional<!IsArray, int, int[]>::type VT;
    109   {
    110     using D = CopyOnlyDeleter;
    111     using U = std::unique_ptr<VT, D>;
    112     static_assert(std::is_nothrow_constructible<U, int*, D const&>::value, "");
    113     static_assert(std::is_nothrow_constructible<U, int*, D&>::value, "");
    114     static_assert(std::is_nothrow_constructible<U, int*, D&&>::value, "");
    115   }
    116   {
    117     using D = MoveOnlyDeleter;
    118     using U = std::unique_ptr<VT, D>;
    119     static_assert(std::is_nothrow_constructible<U, int*, D&&>::value, "");
    120     D d;
    121     U u(nullptr, std::move(d));
    122   }
    123   {
    124     using D = NoCopyMoveDeleter;
    125     using U = std::unique_ptr<VT, D&>;
    126     static_assert(std::is_nothrow_constructible<U, int*, D&>::value, "");
    127   }
    128   {
    129     using D = NoCopyMoveDeleter;
    130     using U = std::unique_ptr<VT, const D&>;
    131     static_assert(std::is_nothrow_constructible<U, int*, D const&>::value, "");
    132     static_assert(std::is_nothrow_constructible<U, int*, D&>::value, "");
    133   }
    134 #endif
    135 }
    136 
    137 void test_sfinae_runtime() {
    138 #if TEST_STD_VER >= 11
    139   {
    140     using D = CopyOnlyDeleter;
    141     using U = std::unique_ptr<A[], D>;
    142     static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
    143     static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
    144     static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
    145 
    146     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
    147     static_assert(!std::is_constructible<U, B*, D&>::value, "");
    148     static_assert(!std::is_constructible<U, B*, D&&>::value, "");
    149     // FIXME: __libcpp_compressed_pair attempts to perform a move even though
    150     // it should only copy.
    151     //D d;
    152     //U u(nullptr, std::move(d));
    153   }
    154   {
    155     using D = MoveOnlyDeleter;
    156     using U = std::unique_ptr<A[], D>;
    157     static_assert(!std::is_constructible<U, A*, D const&>::value, "");
    158     static_assert(!std::is_constructible<U, A*, D&>::value, "");
    159     static_assert(std::is_nothrow_constructible<U, A*, D&&>::value, "");
    160 
    161     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
    162     static_assert(!std::is_constructible<U, B*, D&>::value, "");
    163     static_assert(!std::is_constructible<U, B*, D&&>::value, "");
    164     D d;
    165     U u(nullptr, std::move(d));
    166   }
    167   {
    168     using D = NoCopyMoveDeleter;
    169     using U = std::unique_ptr<A[], D>;
    170     static_assert(!std::is_constructible<U, A*, D const&>::value, "");
    171     static_assert(!std::is_constructible<U, A*, D&>::value, "");
    172     static_assert(!std::is_constructible<U, A*, D&&>::value, "");
    173 
    174     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
    175     static_assert(!std::is_constructible<U, B*, D&>::value, "");
    176     static_assert(!std::is_constructible<U, B*, D&&>::value, "");
    177   }
    178   {
    179     using D = NoCopyMoveDeleter;
    180     using U = std::unique_ptr<A[], D&>;
    181     static_assert(!std::is_constructible<U, A*, D const&>::value, "");
    182     static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
    183     static_assert(!std::is_constructible<U, A*, D&&>::value, "");
    184     static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
    185 
    186     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
    187     static_assert(!std::is_constructible<U, B*, D&>::value, "");
    188     static_assert(!std::is_constructible<U, B*, D&&>::value, "");
    189     static_assert(!std::is_constructible<U, B*, const D&&>::value, "");
    190   }
    191   {
    192     using D = NoCopyMoveDeleter;
    193     using U = std::unique_ptr<A[], const D&>;
    194     static_assert(std::is_nothrow_constructible<U, A*, D const&>::value, "");
    195     static_assert(std::is_nothrow_constructible<U, A*, D&>::value, "");
    196     static_assert(!std::is_constructible<U, A*, D&&>::value, "");
    197     static_assert(!std::is_constructible<U, A*, const D&&>::value, "");
    198 
    199     static_assert(!std::is_constructible<U, B*, D const&>::value, "");
    200     static_assert(!std::is_constructible<U, B*, D&>::value, "");
    201     static_assert(!std::is_constructible<U, B*, D&&>::value, "");
    202     static_assert(!std::is_constructible<U, B*, const D&&>::value, "");
    203   }
    204 #endif
    205 }
    206 
    207 template <bool IsArray>
    208 void test_basic() {
    209   typedef typename std::conditional<!IsArray, A, A[]>::type VT;
    210   const int expect_alive = IsArray ? 5 : 1;
    211   { // MoveConstructible deleter (C-1)
    212     A* p = newValue<VT>(expect_alive);
    213     assert(A::count == expect_alive);
    214     std::unique_ptr<VT, Deleter<VT> > s(p, Deleter<VT>(5));
    215     assert(s.get() == p);
    216     assert(s.get_deleter().state() == 5);
    217   }
    218   assert(A::count == 0);
    219   { // CopyConstructible deleter (C-2)
    220     A* p = newValue<VT>(expect_alive);
    221     assert(A::count == expect_alive);
    222     CopyDeleter<VT> d(5);
    223     std::unique_ptr<VT, CopyDeleter<VT> > s(p, d);
    224     assert(s.get() == p);
    225     assert(s.get_deleter().state() == 5);
    226     d.set_state(6);
    227     assert(s.get_deleter().state() == 5);
    228   }
    229   assert(A::count == 0);
    230   { // Reference deleter (C-3)
    231     A* p = newValue<VT>(expect_alive);
    232     assert(A::count == expect_alive);
    233     NCDeleter<VT> d(5);
    234     std::unique_ptr<VT, NCDeleter<VT>&> s(p, d);
    235     assert(s.get() == p);
    236     assert(&s.get_deleter() == &d);
    237     assert(s.get_deleter().state() == 5);
    238     d.set_state(6);
    239     assert(s.get_deleter().state() == 6);
    240   }
    241   assert(A::count == 0);
    242   { // Const Reference deleter (C-4)
    243     A* p = newValue<VT>(expect_alive);
    244     assert(A::count == expect_alive);
    245     NCConstDeleter<VT> d(5);
    246     std::unique_ptr<VT, NCConstDeleter<VT> const&> s(p, d);
    247     assert(s.get() == p);
    248     assert(s.get_deleter().state() == 5);
    249     assert(&s.get_deleter() == &d);
    250   }
    251   assert(A::count == 0);
    252   { // Void and function pointers (C-6,7)
    253     typedef typename std::conditional<IsArray, int[], int>::type VT2;
    254     my_free_called = false;
    255     {
    256       int i = 0;
    257       std::unique_ptr<VT2, void (*)(void*)> s(&i, my_free);
    258       assert(s.get() == &i);
    259       assert(s.get_deleter() == my_free);
    260       assert(!my_free_called);
    261     }
    262     assert(my_free_called);
    263   }
    264 }
    265 
    266 void test_basic_single() {
    267   assert(A::count == 0);
    268   assert(B::count == 0);
    269   { // Derived pointers (C-5)
    270     B* p = new B;
    271     assert(A::count == 1);
    272     assert(B::count == 1);
    273     std::unique_ptr<A, Deleter<A> > s(p, Deleter<A>(5));
    274     assert(s.get() == p);
    275     assert(s.get_deleter().state() == 5);
    276   }
    277   assert(A::count == 0);
    278   assert(B::count == 0);
    279   { // Void and function pointers (C-6,7)
    280     my_free_called = false;
    281     {
    282       int i = 0;
    283       std::unique_ptr<void, void (*)(void*)> s(&i, my_free);
    284       assert(s.get() == &i);
    285       assert(s.get_deleter() == my_free);
    286       assert(!my_free_called);
    287     }
    288     assert(my_free_called);
    289   }
    290 }
    291 
    292 template <bool IsArray>
    293 void test_nullptr() {
    294 #if TEST_STD_VER >= 11
    295   typedef typename std::conditional<!IsArray, A, A[]>::type VT;
    296   {
    297     std::unique_ptr<VT, Deleter<VT> > u(nullptr, Deleter<VT>{});
    298     assert(u.get() == nullptr);
    299   }
    300   {
    301     NCDeleter<VT> d;
    302     std::unique_ptr<VT, NCDeleter<VT>& > u(nullptr, d);
    303     assert(u.get() == nullptr);
    304   }
    305   {
    306     NCConstDeleter<VT> d;
    307     std::unique_ptr<VT, NCConstDeleter<VT> const& > u(nullptr, d);
    308     assert(u.get() == nullptr);
    309   }
    310 #endif
    311 }
    312 
    313 int main() {
    314   {
    315     test_basic</*IsArray*/ false>();
    316     test_nullptr<false>();
    317     test_basic_single();
    318     test_sfinae<false>();
    319     test_noexcept<false>();
    320   }
    321   {
    322     test_basic</*IsArray*/ true>();
    323     test_nullptr<true>();
    324     test_sfinae<true>();
    325     test_sfinae_runtime();
    326     test_noexcept<true>();
    327   }
    328 }
    329