Home | History | Annotate | Download | only in any.cast
      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
     11 
     12 // <experimental/any>
     13 
     14 // template <class ValueType>
     15 // ValueType const any_cast(any const&);
     16 //
     17 // template <class ValueType>
     18 // ValueType any_cast(any &);
     19 //
     20 // template <class ValueType>
     21 // ValueType any_cast(any &&);
     22 
     23 #include <experimental/any>
     24 #include <type_traits>
     25 #include <cassert>
     26 
     27 #include "experimental_any_helpers.h"
     28 #include "count_new.hpp"
     29 #include "test_macros.h"
     30 
     31 using std::experimental::any;
     32 using std::experimental::any_cast;
     33 using std::experimental::bad_any_cast;
     34 
     35 
     36 // Test that the operators are NOT marked noexcept.
     37 void test_cast_is_not_noexcept() {
     38     any a;
     39     static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), "");
     40     static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), "");
     41     static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), "");
     42 }
     43 
     44 // Test that the return type of any_cast is correct.
     45 void test_cast_return_type() {
     46     any a;
     47     static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, "");
     48     static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, "");
     49     static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, "");
     50     static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, "");
     51 
     52     //static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, "");
     53     //static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, "");
     54 
     55     static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, "");
     56     static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, "");
     57     static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, "");
     58     static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, "");
     59 
     60     //static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, "");
     61     //static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, "");
     62 
     63     any const& ca = a;
     64     static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, "");
     65     static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, "");
     66     static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, "");
     67 
     68     //static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, "");
     69 }
     70 
     71 template <class Type, class ConstT = Type>
     72 void checkThrows(any& a)
     73 {
     74 #if !defined(TEST_HAS_NO_EXCEPTIONS)
     75     try {
     76         any_cast<Type>(a);
     77         assert(false);
     78     } catch (bad_any_cast const &) {
     79             // do nothing
     80     } catch (...) {
     81         assert(false);
     82     }
     83 
     84     try {
     85         any_cast<ConstT>(static_cast<any const&>(a));
     86         assert(false);
     87     } catch (bad_any_cast const &) {
     88             // do nothing
     89     } catch (...) {
     90         assert(false);
     91     }
     92 
     93     try {
     94         any_cast<Type>(static_cast<any&&>(a));
     95         assert(false);
     96     } catch (bad_any_cast const &) {
     97             // do nothing
     98     } catch (...) {
     99         assert(false);
    100     }
    101 #else
    102   ((void)a);
    103 #endif
    104 }
    105 
    106 void test_cast_empty() {
    107     // None of these operations should allocate.
    108     DisableAllocationGuard g; ((void)g);
    109     any a;
    110     checkThrows<int>(a);
    111 }
    112 
    113 template <class Type>
    114 void test_cast_to_reference() {
    115     assert(Type::count == 0);
    116     Type::reset();
    117     {
    118         any a((Type(42)));
    119         any const& ca = a;
    120         assert(Type::count == 1);
    121         assert(Type::copied == 0);
    122         assert(Type::moved == 1);
    123 
    124         // Try a cast to a bad type.
    125         // NOTE: Type cannot be an int.
    126         checkThrows<int>(a);
    127         checkThrows<int&, int const&>(a);
    128         checkThrows<Type*, Type const*>(a);
    129         checkThrows<Type const*>(a);
    130 
    131         // Check getting a type by reference from a non-const lvalue any.
    132         {
    133             Type& v = any_cast<Type&>(a);
    134             assert(v.value == 42);
    135 
    136             Type const &cv = any_cast<Type const&>(a);
    137             assert(&cv == &v);
    138         }
    139         // Check getting a type by reference from a const lvalue any.
    140         {
    141             Type const& v = any_cast<Type const&>(ca);
    142             assert(v.value == 42);
    143 
    144             Type const &cv = any_cast<Type const&>(ca);
    145             assert(&cv == &v);
    146         }
    147         // Check getting a type by reference from a non-const rvalue
    148         {
    149             Type& v = any_cast<Type&>(std::move(a));
    150             assert(v.value == 42);
    151 
    152             Type const &cv = any_cast<Type const&>(std::move(a));
    153             assert(&cv == &v);
    154         }
    155         // Check getting a type by reference from a const rvalue any.
    156         {
    157             Type const& v = any_cast<Type const&>(std::move(ca));
    158             assert(v.value == 42);
    159 
    160             Type const &cv = any_cast<Type const&>(std::move(ca));
    161             assert(&cv == &v);
    162         }
    163 
    164         // Check that the original object hasn't been changed.
    165         assertContains<Type>(a, 42);
    166 
    167         // Check that no objects have been created/copied/moved.
    168         assert(Type::count == 1);
    169         assert(Type::copied == 0);
    170         assert(Type::moved == 1);
    171     }
    172     assert(Type::count == 0);
    173 }
    174 
    175 template <class Type>
    176 void test_cast_to_value() {
    177     assert(Type::count == 0);
    178     Type::reset();
    179     {
    180         any a((Type(42)));
    181         assert(Type::count == 1);
    182         assert(Type::copied == 0);
    183         assert(Type::moved == 1);
    184 
    185         // Try a cast to a bad type.
    186         // NOTE: Type cannot be an int.
    187         checkThrows<int>(a);
    188         checkThrows<int&, int const&>(a);
    189         checkThrows<Type*, Type const*>(a);
    190         checkThrows<Type const*>(a);
    191 
    192         Type::reset(); // NOTE: reset does not modify Type::count
    193         // Check getting Type by value from a non-const lvalue any.
    194         // This should cause the non-const copy constructor to be called.
    195         {
    196             Type t = any_cast<Type>(a);
    197 
    198             assert(Type::count == 2);
    199             assert(Type::copied == 1);
    200             assert(Type::const_copied == 0);
    201             assert(Type::non_const_copied == 1);
    202             assert(Type::moved == 0);
    203             assert(t.value == 42);
    204         }
    205         assert(Type::count == 1);
    206         Type::reset();
    207         // Check getting const Type by value from a non-const lvalue any.
    208         // This should cause the const copy constructor to be called.
    209         {
    210             Type t = any_cast<Type const>(a);
    211 
    212             assert(Type::count == 2);
    213             assert(Type::copied == 1);
    214             assert(Type::const_copied == 1);
    215             assert(Type::non_const_copied == 0);
    216             assert(Type::moved == 0);
    217             assert(t.value == 42);
    218         }
    219         assert(Type::count == 1);
    220         Type::reset();
    221         // Check getting Type by value from a non-const lvalue any.
    222         // This should cause the const copy constructor to be called.
    223         {
    224             Type t = any_cast<Type>(static_cast<any const&>(a));
    225 
    226             assert(Type::count == 2);
    227             assert(Type::copied == 1);
    228             assert(Type::const_copied == 1);
    229             assert(Type::non_const_copied == 0);
    230             assert(Type::moved == 0);
    231             assert(t.value == 42);
    232         }
    233         assert(Type::count == 1);
    234         Type::reset();
    235         // Check getting Type by value from a non-const rvalue any.
    236         // This should cause the non-const copy constructor to be called.
    237         {
    238             Type t = any_cast<Type>(static_cast<any &&>(a));
    239 
    240             assert(Type::count == 2);
    241             assert(Type::copied == 1);
    242             assert(Type::const_copied == 0);
    243             assert(Type::non_const_copied == 1);
    244             assert(Type::moved == 0);
    245             assert(t.value == 42);
    246         }
    247         assert(Type::count == 1);
    248         Type::reset();
    249         // Check getting const Type by value from a non-const rvalue any.
    250         // This should cause the const copy constructor to be called.
    251         {
    252             Type t = any_cast<Type const>(static_cast<any &&>(a));
    253 
    254             assert(Type::count == 2);
    255             assert(Type::copied == 1);
    256             assert(Type::const_copied == 1);
    257             assert(Type::non_const_copied == 0);
    258             assert(Type::moved == 0);
    259             assert(t.value == 42);
    260         }
    261         assert(Type::count == 1);
    262         Type::reset();
    263         // Check getting Type by value from a const rvalue any.
    264         // This should cause the const copy constructor to be called.
    265         {
    266             Type t = any_cast<Type>(static_cast<any const&&>(a));
    267 
    268             assert(Type::count == 2);
    269             assert(Type::copied == 1);
    270             assert(Type::const_copied == 1);
    271             assert(Type::non_const_copied == 0);
    272             assert(Type::moved == 0);
    273             assert(t.value == 42);
    274         }
    275         // Ensure we still only have 1 Type object alive.
    276         assert(Type::count == 1);
    277 
    278         // Check that the original object hasn't been changed.
    279         assertContains<Type>(a, 42);
    280     }
    281     assert(Type::count == 0);
    282 }
    283 
    284 // Even though you can't get a non-copyable class into std::any
    285 // the standard requires that these overloads compile and function.
    286 void test_non_copyable_ref() {
    287     struct no_copy
    288     {
    289         no_copy() {}
    290         no_copy(no_copy &&) {}
    291     private:
    292         no_copy(no_copy const &);
    293     };
    294 
    295     any a;
    296     checkThrows<no_copy &, no_copy const&>(a);
    297     checkThrows<no_copy const&>(a);
    298     assertEmpty(a);
    299 }
    300 
    301 int main() {
    302     test_cast_is_not_noexcept();
    303     test_cast_return_type();
    304     test_cast_empty();
    305     test_cast_to_reference<small>();
    306     test_cast_to_reference<large>();
    307     test_cast_to_value<small>();
    308     test_cast_to_value<large>();
    309     test_non_copyable_ref();
    310 }
    311