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