libcxx

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

move_convert.pass.cpp (7097B)


      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 ctor
     17 
     18 #include <memory>
     19 #include <cassert>
     20 
     21 #include "test_macros.h"
     22 #include "type_id.h"
     23 #include "unique_ptr_test_helper.h"
     24 
     25 template <int ID = 0>
     26 struct GenericDeleter {
     27   void operator()(void*) const {}
     28 };
     29 
     30 template <int ID = 0>
     31 struct GenericConvertingDeleter {
     32   template <int OID>
     33   GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
     34   void operator()(void*) const {}
     35 };
     36 
     37 template <class Templ, class Other>
     38 struct is_specialization;
     39 
     40 template <template <int> class Templ, int ID1, class Other>
     41 struct is_specialization<Templ<ID1>, Other> : std::false_type {};
     42 
     43 template <template <int> class Templ, int ID1, int ID2>
     44 struct is_specialization<Templ<ID1>, Templ<ID2> > : std::true_type {};
     45 
     46 template <class Templ, class Other>
     47 using EnableIfSpecialization = typename std::enable_if<
     48     is_specialization<Templ, typename std::decay<Other>::type >::value
     49   >::type;
     50 
     51 
     52 template <int ID>
     53 struct TrackingDeleter {
     54   TrackingDeleter() : arg_type(&makeArgumentID<>()) {}
     55 
     56   TrackingDeleter(TrackingDeleter const&)
     57       : arg_type(&makeArgumentID<TrackingDeleter const&>()) {}
     58 
     59   TrackingDeleter(TrackingDeleter&&)
     60       : arg_type(&makeArgumentID<TrackingDeleter &&>()) {}
     61 
     62   template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
     63   TrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
     64 
     65   TrackingDeleter& operator=(TrackingDeleter const&) {
     66     arg_type = &makeArgumentID<TrackingDeleter const&>();
     67     return *this;
     68   }
     69 
     70   TrackingDeleter& operator=(TrackingDeleter &&) {
     71     arg_type = &makeArgumentID<TrackingDeleter &&>();
     72     return *this;
     73   }
     74 
     75   template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
     76   TrackingDeleter& operator=(T&&) {
     77     arg_type = &makeArgumentID<T&&>();
     78     return *this;
     79   }
     80 
     81   void operator()(void*) const {}
     82 
     83 public:
     84   TypeID const* reset() const {
     85     TypeID const* tmp = arg_type;
     86     arg_type = nullptr;
     87     return tmp;
     88   }
     89 
     90   mutable TypeID const* arg_type;
     91 };
     92 
     93 
     94 template <class ExpectT, int ID>
     95 bool checkArg(TrackingDeleter<ID> const& d) {
     96   return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
     97 }
     98 
     99 
    100 template <bool IsArray>
    101 void test_sfinae() {
    102   typedef typename std::conditional<IsArray, A[], A>::type VT;
    103 
    104   { // Test that different non-reference deleter types are allowed so long
    105     // as they convert to each other.
    106     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    107     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    108     static_assert(std::is_constructible<U1, U2&&>::value, "");
    109   }
    110   { // Test that different non-reference deleter types are disallowed when
    111     // they cannot convert.
    112     using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
    113     using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
    114     static_assert(!std::is_constructible<U1, U2&&>::value, "");
    115   }
    116   { // Test that if the destination deleter is a reference type then only
    117     // exact matches are allowed.
    118     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
    119     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    120     using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
    121     using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    122     using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
    123     static_assert(!std::is_constructible<U1, U2&&>::value, "");
    124     static_assert(!std::is_constructible<U1, U3&&>::value, "");
    125     static_assert(!std::is_constructible<U1, U4&&>::value, "");
    126     static_assert(!std::is_constructible<U1, U5&&>::value, "");
    127 
    128     using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
    129     static_assert(std::is_nothrow_constructible<U1C, U1&&>::value, "");
    130   }
    131   { // Test that non-reference destination deleters can be constructed
    132     // from any source deleter type with a sutible conversion. Including
    133     // reference types.
    134     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    135     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
    136     using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
    137     using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    138     using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
    139     using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
    140     static_assert(std::is_constructible<U1, U2&&>::value, "");
    141     static_assert(std::is_constructible<U1, U3&&>::value, "");
    142     static_assert(std::is_constructible<U1, U4&&>::value, "");
    143     static_assert(std::is_constructible<U1, U5&&>::value, "");
    144     static_assert(std::is_constructible<U1, U6&&>::value, "");
    145   }
    146 }
    147 
    148 
    149 template <bool IsArray>
    150 void test_noexcept() {
    151   typedef typename std::conditional<IsArray, A[], A>::type VT;
    152   {
    153     typedef std::unique_ptr<const VT> APtr;
    154     typedef std::unique_ptr<VT> BPtr;
    155     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    156   }
    157   {
    158     typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
    159     typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
    160     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    161   }
    162   {
    163     typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
    164     typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
    165     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    166   }
    167   {
    168     typedef std::unique_ptr<const VT, const NCConstDeleter<const VT>&> APtr;
    169     typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr;
    170     static_assert(std::is_nothrow_constructible<APtr, BPtr>::value, "");
    171   }
    172 }
    173 
    174 
    175 template <bool IsArray>
    176 void test_deleter_value_category() {
    177   typedef typename std::conditional<IsArray, A[], A>::type VT;
    178   using TD1 = TrackingDeleter<1>;
    179   using TD2 = TrackingDeleter<2>;
    180   TD1 d1;
    181   TD2 d2;
    182 
    183   { // Test non-reference deleter conversions
    184     using U1 = std::unique_ptr<VT, TD1 >;
    185     using U2 = std::unique_ptr<VT, TD2 >;
    186     U2 u2;
    187     u2.get_deleter().reset();
    188     U1 u1(std::move(u2));
    189     assert(checkArg<TD2&&>(u1.get_deleter()));
    190   }
    191   { // Test assignment from non-const ref
    192     using U1 = std::unique_ptr<VT, TD1 >;
    193     using U2 = std::unique_ptr<VT, TD2& >;
    194     U2 u2(nullptr, d2);
    195     U1 u1(std::move(u2));
    196     assert(checkArg<TD2&>(u1.get_deleter()));
    197   }
    198   { // Test assignment from const ref
    199     using U1 = std::unique_ptr<VT, TD1 >;
    200     using U2 = std::unique_ptr<VT, TD2 const& >;
    201     U2 u2(nullptr, d2);
    202     U1 u1(std::move(u2));
    203     assert(checkArg<TD2 const&>(u1.get_deleter()));
    204   }
    205 }
    206 
    207 
    208 int main() {
    209   {
    210     test_sfinae</*IsArray*/false>();
    211     test_noexcept<false>();
    212     test_deleter_value_category<false>();
    213   }
    214   {
    215     test_sfinae</*IsArray*/true>();
    216     test_noexcept<true>();
    217     test_deleter_value_category<true>();
    218   }
    219 }