Home | History | Annotate | Download | only in any.cons
      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 // <any>
     13 
     14 // template <class Value> any(Value &&)
     15 
     16 // Test construction from a value.
     17 // Concerns:
     18 // ---------
     19 // 1. The value is properly move/copied depending on the value category.
     20 // 2. Both small and large values are properly handled.
     21 
     22 
     23 #include <any>
     24 #include <cassert>
     25 
     26 #include "any_helpers.h"
     27 #include "count_new.hpp"
     28 #include "test_macros.h"
     29 
     30 using std::any;
     31 using std::any_cast;
     32 
     33 template <class Type>
     34 void test_copy_value_throws()
     35 {
     36 #if !defined(TEST_HAS_NO_EXCEPTIONS)
     37     assert(Type::count == 0);
     38     {
     39         Type const t(42);
     40         assert(Type::count == 1);
     41         try {
     42             any const a2(t);
     43             assert(false);
     44         } catch (my_any_exception const &) {
     45             // do nothing
     46         } catch (...) {
     47             assert(false);
     48         }
     49         assert(Type::count == 1);
     50         assert(t.value == 42);
     51     }
     52     assert(Type::count == 0);
     53 #endif
     54 }
     55 
     56 void test_move_value_throws()
     57 {
     58 #if !defined(TEST_HAS_NO_EXCEPTIONS)
     59     assert(throws_on_move::count == 0);
     60     {
     61         throws_on_move v;
     62         assert(throws_on_move::count == 1);
     63         try {
     64             any const a(std::move(v));
     65             assert(false);
     66         } catch (my_any_exception const &) {
     67             // do nothing
     68         } catch (...) {
     69             assert(false);
     70         }
     71         assert(throws_on_move::count == 1);
     72     }
     73     assert(throws_on_move::count == 0);
     74 #endif
     75 }
     76 
     77 template <class Type>
     78 void test_copy_move_value() {
     79     // constructing from a small type should perform no allocations.
     80     DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
     81     assert(Type::count == 0);
     82     Type::reset();
     83     {
     84         Type t(42);
     85         assert(Type::count == 1);
     86 
     87         any a(t);
     88 
     89         assert(Type::count == 2);
     90         assert(Type::copied == 1);
     91         assert(Type::moved == 0);
     92         assertContains<Type>(a, 42);
     93     }
     94     assert(Type::count == 0);
     95     Type::reset();
     96     {
     97         Type t(42);
     98         assert(Type::count == 1);
     99 
    100         any a(std::move(t));
    101 
    102         assert(Type::count == 2);
    103         assert(Type::copied == 0);
    104         assert(Type::moved == 1);
    105         assertContains<Type>(a, 42);
    106     }
    107 }
    108 
    109 // Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization.
    110 void test_sfinae_constraints() {
    111     using BadTag = std::in_place_type_t<int>;
    112     using OKTag = std::in_place_t;
    113     // Test that the tag type is properly handled in SFINAE
    114     BadTag t = std::in_place_type<int>;
    115     OKTag ot = std::in_place;
    116     {
    117         std::any a(t);
    118         assertContains<int>(a, 0);
    119     }
    120     {
    121         std::any a(std::move(t));
    122         assertContains<int>(a, 0);
    123     }
    124     {
    125         std::any a(ot);
    126         assert(containsType<OKTag>(a));
    127     }
    128     {
    129         struct Dummy { Dummy() = delete; };
    130         using T = std::in_place_type_t<Dummy>;
    131         static_assert(!std::is_constructible<std::any, T>::value, "");
    132     }
    133     {
    134         // Test that the ValueType&& constructor SFINAE's away when the
    135         // argument is non-copyable
    136         struct NoCopy {
    137           NoCopy() = default;
    138           NoCopy(NoCopy const&) = delete;
    139           NoCopy(int) {}
    140         };
    141         static_assert(!std::is_constructible<std::any, NoCopy>::value, "");
    142         static_assert(!std::is_constructible<std::any, NoCopy&>::value, "");
    143         static_assert(!std::is_convertible<NoCopy, std::any>::value, "");
    144     }
    145 }
    146 
    147 int main() {
    148     test_copy_move_value<small>();
    149     test_copy_move_value<large>();
    150     test_copy_value_throws<small_throws_on_copy>();
    151     test_copy_value_throws<large_throws_on_copy>();
    152     test_move_value_throws();
    153     test_sfinae_constraints();
    154 }