libcxx

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

move_convert.pass.cpp (13633B)


      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 "unique_ptr_test_helper.h"
     23 #include "type_id.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 
     33   template <int OID>
     34   GenericConvertingDeleter(GenericConvertingDeleter<OID>) {}
     35 
     36   template <int OID>
     37   GenericConvertingDeleter& operator=(GenericConvertingDeleter<OID> const&) {
     38     return *this;
     39   }
     40 
     41   void operator()(void*) const {}
     42 };
     43 
     44 template <class T, class U>
     45 using EnableIfNotSame = typename std::enable_if<
     46     !std::is_same<typename std::decay<T>::type, typename std::decay<U>::type>::value
     47 >::type;
     48 
     49 template <class Templ, class Other>
     50 struct is_specialization;
     51 
     52 template <template <int> class Templ, int ID1, class Other>
     53 struct is_specialization<Templ<ID1>, Other> : std::false_type {};
     54 
     55 template <template <int> class Templ, int ID1, int ID2>
     56 struct is_specialization<Templ<ID1>, Templ<ID2> > : std::true_type {};
     57 
     58 template <class Templ, class Other>
     59 using EnableIfSpecialization = typename std::enable_if<
     60     is_specialization<Templ, typename std::decay<Other>::type >::value
     61   >::type;
     62 
     63 template <int ID> struct TrackingDeleter;
     64 template <int ID> struct ConstTrackingDeleter;
     65 
     66 template <int ID>
     67 struct TrackingDeleter {
     68   TrackingDeleter() : arg_type(&makeArgumentID<>()) {}
     69 
     70   TrackingDeleter(TrackingDeleter const&)
     71       : arg_type(&makeArgumentID<TrackingDeleter const&>()) {}
     72 
     73   TrackingDeleter(TrackingDeleter&&)
     74       : arg_type(&makeArgumentID<TrackingDeleter &&>()) {}
     75 
     76   template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
     77   TrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
     78 
     79   TrackingDeleter& operator=(TrackingDeleter const&) {
     80     arg_type = &makeArgumentID<TrackingDeleter const&>();
     81     return *this;
     82   }
     83 
     84   TrackingDeleter& operator=(TrackingDeleter &&) {
     85     arg_type = &makeArgumentID<TrackingDeleter &&>();
     86     return *this;
     87   }
     88 
     89   template <class T, class = EnableIfSpecialization<TrackingDeleter, T> >
     90   TrackingDeleter& operator=(T&&) {
     91     arg_type = &makeArgumentID<T&&>();
     92     return *this;
     93   }
     94 
     95   void operator()(void*) const {}
     96 
     97 public:
     98   TypeID const* reset() const {
     99     TypeID const* tmp = arg_type;
    100     arg_type = nullptr;
    101     return tmp;
    102   }
    103 
    104   mutable TypeID const* arg_type;
    105 };
    106 
    107 template <int ID>
    108 struct ConstTrackingDeleter {
    109   ConstTrackingDeleter() : arg_type(&makeArgumentID<>()) {}
    110 
    111   ConstTrackingDeleter(ConstTrackingDeleter const&)
    112       : arg_type(&makeArgumentID<ConstTrackingDeleter const&>()) {}
    113 
    114   ConstTrackingDeleter(ConstTrackingDeleter&&)
    115       : arg_type(&makeArgumentID<ConstTrackingDeleter &&>()) {}
    116 
    117   template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
    118   ConstTrackingDeleter(T&&) : arg_type(&makeArgumentID<T&&>()) {}
    119 
    120   const ConstTrackingDeleter& operator=(ConstTrackingDeleter const&) const {
    121     arg_type = &makeArgumentID<ConstTrackingDeleter const&>();
    122     return *this;
    123   }
    124 
    125   const ConstTrackingDeleter& operator=(ConstTrackingDeleter &&) const {
    126     arg_type = &makeArgumentID<ConstTrackingDeleter &&>();
    127     return *this;
    128   }
    129 
    130   template <class T, class = EnableIfSpecialization<ConstTrackingDeleter, T> >
    131   const ConstTrackingDeleter& operator=(T&&) const {
    132     arg_type = &makeArgumentID<T&&>();
    133     return *this;
    134   }
    135 
    136   void operator()(void*) const {}
    137 
    138 public:
    139   TypeID const* reset() const {
    140     TypeID const* tmp = arg_type;
    141     arg_type = nullptr;
    142     return tmp;
    143   }
    144 
    145   mutable TypeID const* arg_type;
    146 };
    147 
    148 template <class ExpectT, int ID>
    149 bool checkArg(TrackingDeleter<ID> const& d) {
    150   return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
    151 }
    152 
    153 template <class ExpectT, int ID>
    154 bool checkArg(ConstTrackingDeleter<ID> const& d) {
    155   return d.arg_type && *d.arg_type == makeArgumentID<ExpectT>();
    156 }
    157 
    158 template <class From, bool AssignIsConst = false>
    159 struct AssignDeleter {
    160   AssignDeleter() = default;
    161   AssignDeleter(AssignDeleter const&) = default;
    162   AssignDeleter(AssignDeleter&&) = default;
    163 
    164   AssignDeleter& operator=(AssignDeleter const&) = delete;
    165   AssignDeleter& operator=(AssignDeleter &&) = delete;
    166 
    167   template <class T> AssignDeleter& operator=(T&&) && = delete;
    168   template <class T> AssignDeleter& operator=(T&&) const && = delete;
    169 
    170   template <class T, class = typename std::enable_if<
    171       std::is_same<T&&, From>::value && !AssignIsConst
    172     >::type>
    173   AssignDeleter& operator=(T&&) & { return *this; }
    174 
    175   template <class T, class = typename std::enable_if<
    176       std::is_same<T&&, From>::value && AssignIsConst
    177     >::type>
    178   const AssignDeleter& operator=(T&&) const & { return *this; }
    179 
    180   template <class T>
    181   void operator()(T) const {}
    182 };
    183 
    184 template <class VT, class DDest, class DSource>
    185   void doDeleterTest() {
    186     using U1 = std::unique_ptr<VT, DDest>;
    187     using U2 = std::unique_ptr<VT, DSource>;
    188     static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
    189     typename std::decay<DDest>::type ddest;
    190     typename std::decay<DSource>::type dsource;
    191     U1 u1(nullptr, ddest);
    192     U2 u2(nullptr, dsource);
    193     u1 = std::move(u2);
    194 }
    195 
    196 template <bool IsArray>
    197 void test_sfinae() {
    198   typedef typename std::conditional<IsArray, A[], A>::type VT;
    199 
    200   { // Test that different non-reference deleter types are allowed so long
    201     // as they convert to each other.
    202     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    203     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    204     static_assert(std::is_assignable<U1, U2&&>::value, "");
    205   }
    206   { // Test that different non-reference deleter types are disallowed when
    207     // they cannot convert.
    208     using U1 = std::unique_ptr<VT, GenericDeleter<0> >;
    209     using U2 = std::unique_ptr<VT, GenericDeleter<1> >;
    210     static_assert(!std::is_assignable<U1, U2&&>::value, "");
    211   }
    212   { // Test that if the deleter assignment is not valid the assignment operator
    213     // SFINAEs.
    214     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> const& >;
    215     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    216     using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
    217     using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    218     using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
    219     static_assert(!std::is_assignable<U1, U2&&>::value, "");
    220     static_assert(!std::is_assignable<U1, U3&&>::value, "");
    221     static_assert(!std::is_assignable<U1, U4&&>::value, "");
    222     static_assert(!std::is_assignable<U1, U5&&>::value, "");
    223 
    224     using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> const&>;
    225     static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
    226   }
    227   { // Test that if the deleter assignment is not valid the assignment operator
    228     // SFINAEs.
    229     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> & >;
    230     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    231     using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
    232     using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    233     using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
    234 
    235     static_assert(std::is_nothrow_assignable<U1, U2&&>::value, "");
    236     static_assert(std::is_nothrow_assignable<U1, U3&&>::value, "");
    237     static_assert(std::is_nothrow_assignable<U1, U4&&>::value, "");
    238     static_assert(std::is_nothrow_assignable<U1, U5&&>::value, "");
    239 
    240     using U1C = std::unique_ptr<const VT, GenericConvertingDeleter<0> &>;
    241     static_assert(std::is_nothrow_assignable<U1C, U1&&>::value, "");
    242   }
    243   { // Test that non-reference destination deleters can be assigned
    244     // from any source deleter type with a sutible conversion. Including
    245     // reference types.
    246     using U1 = std::unique_ptr<VT, GenericConvertingDeleter<0> >;
    247     using U2 = std::unique_ptr<VT, GenericConvertingDeleter<0> &>;
    248     using U3 = std::unique_ptr<VT, GenericConvertingDeleter<0> const &>;
    249     using U4 = std::unique_ptr<VT, GenericConvertingDeleter<1> >;
    250     using U5 = std::unique_ptr<VT, GenericConvertingDeleter<1> &>;
    251     using U6 = std::unique_ptr<VT, GenericConvertingDeleter<1> const&>;
    252     static_assert(std::is_assignable<U1, U2&&>::value, "");
    253     static_assert(std::is_assignable<U1, U3&&>::value, "");
    254     static_assert(std::is_assignable<U1, U4&&>::value, "");
    255     static_assert(std::is_assignable<U1, U5&&>::value, "");
    256     static_assert(std::is_assignable<U1, U6&&>::value, "");
    257   }
    258   /////////////////////////////////////////////////////////////////////////////
    259   {
    260     using Del = GenericDeleter<0>;
    261     using AD = AssignDeleter<Del&&>;
    262     using ADC = AssignDeleter<Del&&, /*AllowConstAssign*/true>;
    263     doDeleterTest<VT, AD, Del>();
    264     doDeleterTest<VT, AD&, Del>();
    265     doDeleterTest<VT, ADC const&, Del>();
    266   }
    267   {
    268     using Del = GenericDeleter<0>;
    269     using AD = AssignDeleter<Del&>;
    270     using ADC = AssignDeleter<Del&, /*AllowConstAssign*/true>;
    271     doDeleterTest<VT, AD, Del&>();
    272     doDeleterTest<VT, AD&, Del&>();
    273     doDeleterTest<VT, ADC const&, Del&>();
    274   }
    275   {
    276     using Del = GenericDeleter<0>;
    277     using AD = AssignDeleter<Del const&>;
    278     using ADC = AssignDeleter<Del const&, /*AllowConstAssign*/true>;
    279     doDeleterTest<VT, AD, Del const&>();
    280     doDeleterTest<VT, AD&, Del const&>();
    281     doDeleterTest<VT, ADC const&, Del const&>();
    282   }
    283 }
    284 
    285 
    286 template <bool IsArray>
    287 void test_noexcept() {
    288   typedef typename std::conditional<IsArray, A[], A>::type VT;
    289   {
    290     typedef std::unique_ptr<const VT> APtr;
    291     typedef std::unique_ptr<VT> BPtr;
    292     static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
    293   }
    294   {
    295     typedef std::unique_ptr<const VT, CDeleter<const VT> > APtr;
    296     typedef std::unique_ptr<VT, CDeleter<VT> > BPtr;
    297     static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
    298   }
    299   {
    300     typedef std::unique_ptr<const VT, NCDeleter<const VT>&> APtr;
    301     typedef std::unique_ptr<VT, NCDeleter<const VT>&> BPtr;
    302     static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
    303   }
    304   {
    305     typedef std::unique_ptr<const VT, const NCConstDeleter<const VT>&> APtr;
    306     typedef std::unique_ptr<VT, const NCConstDeleter<const VT>&> BPtr;
    307     static_assert(std::is_nothrow_assignable<APtr, BPtr>::value, "");
    308   }
    309 }
    310 
    311 template <bool IsArray>
    312 void test_deleter_value_category() {
    313   typedef typename std::conditional<IsArray, A[], A>::type VT;
    314   using TD1 = TrackingDeleter<1>;
    315   using TD2 = TrackingDeleter<2>;
    316   TD1 d1;
    317   TD2 d2;
    318   using CD1 = ConstTrackingDeleter<1>;
    319   using CD2 = ConstTrackingDeleter<2>;
    320   CD1 cd1;
    321   CD2 cd2;
    322 
    323   { // Test non-reference deleter conversions
    324     using U1 = std::unique_ptr<VT, TD1 >;
    325     using U2 = std::unique_ptr<VT, TD2 >;
    326     U1 u1;
    327     U2 u2;
    328     u1.get_deleter().reset();
    329     u1 = std::move(u2);
    330     assert(checkArg<TD2&&>(u1.get_deleter()));
    331   }
    332   { // Test assignment to non-const ref
    333     using U1 = std::unique_ptr<VT, TD1& >;
    334     using U2 = std::unique_ptr<VT, TD2 >;
    335     U1 u1(nullptr, d1);
    336     U2 u2;
    337     u1.get_deleter().reset();
    338     u1 = std::move(u2);
    339     assert(checkArg<TD2&&>(u1.get_deleter()));
    340   }
    341   { // Test assignment to const&.
    342     using U1 = std::unique_ptr<VT, CD1 const& >;
    343     using U2 = std::unique_ptr<VT, CD2 >;
    344     U1 u1(nullptr, cd1);
    345     U2 u2;
    346     u1.get_deleter().reset();
    347     u1 = std::move(u2);
    348     assert(checkArg<CD2&&>(u1.get_deleter()));
    349   }
    350 
    351   { // Test assignment from non-const ref
    352     using U1 = std::unique_ptr<VT, TD1 >;
    353     using U2 = std::unique_ptr<VT, TD2& >;
    354     U1 u1;
    355     U2 u2(nullptr, d2);
    356     u1.get_deleter().reset();
    357     u1 = std::move(u2);
    358     assert(checkArg<TD2&>(u1.get_deleter()));
    359   }
    360   { // Test assignment from const ref
    361     using U1 = std::unique_ptr<VT, TD1 >;
    362     using U2 = std::unique_ptr<VT, TD2 const& >;
    363     U1 u1;
    364     U2 u2(nullptr, d2);
    365     u1.get_deleter().reset();
    366     u1 = std::move(u2);
    367     assert(checkArg<TD2 const&>(u1.get_deleter()));
    368   }
    369 
    370   { // Test assignment from non-const ref
    371     using U1 = std::unique_ptr<VT, TD1& >;
    372     using U2 = std::unique_ptr<VT, TD2& >;
    373     U1 u1(nullptr, d1);
    374     U2 u2(nullptr, d2);
    375     u1.get_deleter().reset();
    376     u1 = std::move(u2);
    377     assert(checkArg<TD2&>(u1.get_deleter()));
    378   }
    379   { // Test assignment from const ref
    380     using U1 = std::unique_ptr<VT, TD1& >;
    381     using U2 = std::unique_ptr<VT, TD2 const& >;
    382     U1 u1(nullptr, d1);
    383     U2 u2(nullptr, d2);
    384     u1.get_deleter().reset();
    385     u1 = std::move(u2);
    386     assert(checkArg<TD2 const&>(u1.get_deleter()));
    387   }
    388 
    389   { // Test assignment from non-const ref
    390     using U1 = std::unique_ptr<VT, CD1 const& >;
    391     using U2 = std::unique_ptr<VT, CD2 & >;
    392     U1 u1(nullptr, cd1);
    393     U2 u2(nullptr, cd2);
    394     u1.get_deleter().reset();
    395     u1 = std::move(u2);
    396     assert(checkArg<CD2 &>(u1.get_deleter()));
    397   }
    398   { // Test assignment from const ref
    399     using U1 = std::unique_ptr<VT, CD1 const& >;
    400     using U2 = std::unique_ptr<VT, CD2 const& >;
    401     U1 u1(nullptr, cd1);
    402     U2 u2(nullptr, cd2);
    403     u1.get_deleter().reset();
    404     u1 = std::move(u2);
    405     assert(checkArg<CD2 const&>(u1.get_deleter()));
    406   }
    407 }
    408 
    409 int main() {
    410   {
    411     test_sfinae</*IsArray*/false>();
    412     test_noexcept<false>();
    413     test_deleter_value_category<false>();
    414   }
    415   {
    416     test_sfinae</*IsArray*/true>();
    417     test_noexcept<true>();
    418     test_deleter_value_category<true>();
    419   }
    420 }