libcxx

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

emplace.pass.cpp (9037B)


      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, c++11, c++14
     11 
     12 // XFAIL: availability=macosx10.13
     13 // XFAIL: availability=macosx10.12
     14 // XFAIL: availability=macosx10.11
     15 // XFAIL: availability=macosx10.10
     16 // XFAIL: availability=macosx10.9
     17 // XFAIL: availability=macosx10.8
     18 // XFAIL: availability=macosx10.7
     19 
     20 // <any>
     21 
     22 // template <class T, class ...Args> T& emplace(Args&&...);
     23 // template <class T, class U, class ...Args>
     24 // T& emplace(initializer_list<U>, Args&&...);
     25 
     26 #include <any>
     27 #include <cassert>
     28 
     29 #include "any_helpers.h"
     30 #include "count_new.hpp"
     31 #include "test_macros.h"
     32 
     33 using std::any;
     34 using std::any_cast;
     35 
     36 struct Tracked {
     37   static int count;
     38   Tracked()  {++count;}
     39   ~Tracked() { --count; }
     40 };
     41 int Tracked::count = 0;
     42 
     43 template <class Type>
     44 void test_emplace_type() {
     45     // constructing from a small type should perform no allocations.
     46     DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
     47     assert(Type::count == 0);
     48     Type::reset();
     49     {
     50         any a(std::in_place_type<Tracked>);
     51         assert(Tracked::count == 1);
     52 
     53         auto &v = a.emplace<Type>();
     54         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
     55         assert(&v == std::any_cast<Type>(&a));
     56 
     57         assert(Tracked::count == 0);
     58         assert(Type::count == 1);
     59         assert(Type::copied == 0);
     60         assert(Type::moved == 0);
     61         assertContains<Type>(a, 0);
     62     }
     63     assert(Type::count == 0);
     64     Type::reset();
     65     {
     66         any a(std::in_place_type<Tracked>);
     67         assert(Tracked::count == 1);
     68 
     69         auto &v = a.emplace<Type>(101);
     70         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
     71         assert(&v == std::any_cast<Type>(&a));
     72 
     73         assert(Tracked::count == 0);
     74         assert(Type::count == 1);
     75         assert(Type::copied == 0);
     76         assert(Type::moved == 0);
     77         assertContains<Type>(a, 101);
     78     }
     79     assert(Type::count == 0);
     80     Type::reset();
     81     {
     82         any a(std::in_place_type<Tracked>);
     83         assert(Tracked::count == 1);
     84 
     85         auto &v = a.emplace<Type>(-1, 42, -1);
     86         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
     87         assert(&v == std::any_cast<Type>(&a));
     88 
     89         assert(Tracked::count == 0);
     90         assert(Type::count == 1);
     91         assert(Type::copied == 0);
     92         assert(Type::moved == 0);
     93         assertContains<Type>(a, 42);
     94     }
     95     assert(Type::count == 0);
     96     Type::reset();
     97 }
     98 
     99 template <class Type>
    100 void test_emplace_type_tracked() {
    101     // constructing from a small type should perform no allocations.
    102     DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
    103     {
    104         any a(std::in_place_type<Tracked>);
    105         assert(Tracked::count == 1);
    106         auto &v = a.emplace<Type>();
    107         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    108         assert(&v == std::any_cast<Type>(&a));
    109 
    110         assert(Tracked::count == 0);
    111         assertArgsMatch<Type>(a);
    112     }
    113     {
    114         any a(std::in_place_type<Tracked>);
    115         assert(Tracked::count == 1);
    116         auto &v = a.emplace<Type>(-1, 42, -1);
    117         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    118         assert(&v == std::any_cast<Type>(&a));
    119 
    120         assert(Tracked::count == 0);
    121         assertArgsMatch<Type, int, int, int>(a);
    122     }
    123     // initializer_list constructor tests
    124     {
    125         any a(std::in_place_type<Tracked>);
    126         assert(Tracked::count == 1);
    127         auto &v = a.emplace<Type>({-1, 42, -1});
    128         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    129         assert(&v == std::any_cast<Type>(&a));
    130 
    131         assert(Tracked::count == 0);
    132         assertArgsMatch<Type, std::initializer_list<int>>(a);
    133     }
    134     {
    135         int x = 42;
    136         any a(std::in_place_type<Tracked>);
    137         assert(Tracked::count == 1);
    138         auto &v = a.emplace<Type>({-1, 42, -1}, x);
    139         static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    140         assert(&v == std::any_cast<Type>(&a));
    141 
    142         assert(Tracked::count == 0);
    143         assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
    144     }
    145 }
    146 
    147 #ifndef TEST_HAS_NO_EXCEPTIONS
    148 
    149 struct SmallThrows {
    150   SmallThrows(int) { throw 42; }
    151   SmallThrows(std::initializer_list<int>, int) { throw 42; }
    152 };
    153 static_assert(IsSmallObject<SmallThrows>::value, "");
    154 
    155 struct LargeThrows {
    156   LargeThrows(int) { throw 42; }
    157   LargeThrows(std::initializer_list<int>, int) { throw 42; }
    158   int data[sizeof(std::any)];
    159 };
    160 static_assert(!IsSmallObject<LargeThrows>::value, "");
    161 
    162 template <class Type>
    163 void test_emplace_throws()
    164 {
    165     // any stores small type
    166     {
    167         std::any a(small{42});
    168         assert(small::count == 1);
    169         try {
    170             auto &v = a.emplace<Type>(101);
    171             static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    172             assert(false);
    173         } catch (int const&) {
    174         }
    175         assert(small::count == 0);
    176     }
    177     {
    178         std::any a(small{42});
    179         assert(small::count == 1);
    180         try {
    181             auto &v = a.emplace<Type>({1, 2, 3}, 101);
    182             static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    183             assert(false);
    184         } catch (int const&) {
    185         }
    186         assert(small::count == 0);
    187     }
    188     // any stores large type
    189     {
    190         std::any a(large{42});
    191         assert(large::count == 1);
    192         try {
    193             auto &v = a.emplace<Type>(101);
    194             static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    195             assert(false);
    196         } catch (int const&) {
    197         }
    198         assert(large::count == 0);
    199     }
    200     {
    201         std::any a(large{42});
    202         assert(large::count == 1);
    203         try {
    204             auto &v = a.emplace<Type>({1, 2, 3}, 101);
    205             static_assert( std::is_same_v<Type&, decltype(v)>, "" );
    206             assert(false);
    207         } catch (int const&) {
    208         }
    209         assert(large::count == 0);
    210     }
    211 }
    212 
    213 #endif
    214 
    215 template <class T, class ...Args>
    216 constexpr auto has_emplace(int)
    217     -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }
    218 
    219 template <class ...Args>
    220 constexpr bool has_emplace(long) { return false; }
    221 
    222 template <class ...Args>
    223 constexpr bool has_emplace() { return has_emplace<Args...>(0); }
    224 
    225 
    226 template <class T, class IT, class ...Args>
    227 constexpr auto has_emplace_init_list(int)
    228     -> decltype(std::any{}.emplace<T>(
    229         {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()},
    230         std::declval<Args>()...), true) { return true; }
    231 
    232 template <class ...Args>
    233 constexpr bool has_emplace_init_list(long) { return false; }
    234 
    235 template <class ...Args>
    236 constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }
    237 
    238 
    239 void test_emplace_sfinae_constraints() {
    240     {
    241         static_assert(has_emplace<int>(), "");
    242         static_assert(has_emplace<int, int>(), "");
    243         static_assert(!has_emplace<int, int, int>(), "not constructible");
    244         static_assert(!has_emplace_init_list<int, int>(), "not constructible from il");
    245     }
    246     {
    247         static_assert(has_emplace<small>(), "");
    248         static_assert(has_emplace<large>(), "");
    249         static_assert(!has_emplace<small, void*>(), "");
    250         static_assert(!has_emplace<large, void*>(), "");
    251 
    252         static_assert(has_emplace_init_list<small, int>(), "");
    253         static_assert(has_emplace_init_list<large, int>(), "");
    254         static_assert(!has_emplace_init_list<small, void*>(), "");
    255         static_assert(!has_emplace_init_list<large, void*>(), "");
    256     }
    257     {
    258         // Test that the emplace SFINAE's away when the
    259         // argument is non-copyable
    260         struct NoCopy {
    261           NoCopy() = default;
    262           NoCopy(NoCopy const&) = delete;
    263           NoCopy(int) {}
    264           NoCopy(std::initializer_list<int>, int, int) {}
    265         };
    266         static_assert(!has_emplace<NoCopy>(), "");
    267         static_assert(!has_emplace<NoCopy, int>(), "");
    268         static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), "");
    269         static_assert(!has_emplace<NoCopy&>(), "");
    270         static_assert(!has_emplace<NoCopy&, int>(), "");
    271         static_assert(!has_emplace_init_list<NoCopy&, int, int, int>(), "");
    272         static_assert(!has_emplace<NoCopy&&>(), "");
    273         static_assert(!has_emplace<NoCopy&&, int>(), "");
    274         static_assert(!has_emplace_init_list<NoCopy&&, int, int, int>(), "");
    275 
    276     }
    277 }
    278 
    279 int main() {
    280     test_emplace_type<small>();
    281     test_emplace_type<large>();
    282     test_emplace_type<small_throws_on_copy>();
    283     test_emplace_type<large_throws_on_copy>();
    284     test_emplace_type<throws_on_move>();
    285     test_emplace_type_tracked<small_tracked_t>();
    286     test_emplace_type_tracked<large_tracked_t>();
    287     test_emplace_sfinae_constraints();
    288 #ifndef TEST_HAS_NO_EXCEPTIONS
    289     test_emplace_throws<SmallThrows>();
    290     test_emplace_throws<LargeThrows>();
    291 #endif
    292 }