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 "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 #endif
    102 }
    103 
    104 void test_cast_empty() {
    105     // None of these operations should allocate.
    106     DisableAllocationGuard g; ((void)g);
    107     any a;
    108     checkThrows<int>(a);
    109 }
    110 
    111 template <class Type>
    112 void test_cast_to_reference() {
    113     assert(Type::count == 0);
    114     Type::reset();
    115     {
    116         any a((Type(42)));
    117         any const& ca = a;
    118         assert(Type::count == 1);
    119         assert(Type::copied == 0);
    120         assert(Type::moved == 1);
    121 
    122         // Try a cast to a bad type.
    123         // NOTE: Type cannot be an int.
    124         checkThrows<int>(a);
    125         checkThrows<int&, int const&>(a);
    126         checkThrows<Type*, Type const*>(a);
    127         checkThrows<Type const*>(a);
    128 
    129         // Check getting a type by reference from a non-const lvalue any.
    130         {
    131             Type& v = any_cast<Type&>(a);
    132             assert(v.value == 42);
    133 
    134             Type const &cv = any_cast<Type const&>(a);
    135             assert(&cv == &v);
    136         }
    137         // Check getting a type by reference from a const lvalue any.
    138         {
    139             Type const& v = any_cast<Type const&>(ca);
    140             assert(v.value == 42);
    141 
    142             Type const &cv = any_cast<Type const&>(ca);
    143             assert(&cv == &v);
    144         }
    145         // Check getting a type by reference from a non-const rvalue
    146         {
    147             Type& v = any_cast<Type&>(std::move(a));
    148             assert(v.value == 42);
    149 
    150             Type const &cv = any_cast<Type const&>(std::move(a));
    151             assert(&cv == &v);
    152         }
    153         // Check getting a type by reference from a const rvalue any.
    154         {
    155             Type const& v = any_cast<Type const&>(std::move(ca));
    156             assert(v.value == 42);
    157 
    158             Type const &cv = any_cast<Type const&>(std::move(ca));
    159             assert(&cv == &v);
    160         }
    161 
    162         // Check that the original object hasn't been changed.
    163         assertContains<Type>(a, 42);
    164 
    165         // Check that no objects have been created/copied/moved.
    166         assert(Type::count == 1);
    167         assert(Type::copied == 0);
    168         assert(Type::moved == 1);
    169     }
    170     assert(Type::count == 0);
    171 }
    172 
    173 template <class Type>
    174 void test_cast_to_value() {
    175     assert(Type::count == 0);
    176     Type::reset();
    177     {
    178         any a((Type(42)));
    179         any const& ca = a;
    180         assert(Type::count == 1);
    181         assert(Type::copied == 0);
    182         assert(Type::moved == 1);
    183 
    184         // Try a cast to a bad type.
    185         // NOTE: Type cannot be an int.
    186         checkThrows<int>(a);
    187         checkThrows<int&, int const&>(a);
    188         checkThrows<Type*, Type const*>(a);
    189         checkThrows<Type const*>(a);
    190 
    191         Type::reset(); // NOTE: reset does not modify Type::count
    192         // Check getting Type by value from a non-const lvalue any.
    193         // This should cause the non-const copy constructor to be called.
    194         {
    195             Type t = any_cast<Type>(a);
    196 
    197             assert(Type::count == 2);
    198             assert(Type::copied == 1);
    199             assert(Type::const_copied == 0);
    200             assert(Type::non_const_copied == 1);
    201             assert(Type::moved == 0);
    202             assert(t.value == 42);
    203         }
    204         assert(Type::count == 1);
    205         Type::reset();
    206         // Check getting const Type by value from a non-const lvalue any.
    207         // This should cause the const copy constructor to be called.
    208         {
    209             Type t = any_cast<Type const>(a);
    210 
    211             assert(Type::count == 2);
    212             assert(Type::copied == 1);
    213             assert(Type::const_copied == 1);
    214             assert(Type::non_const_copied == 0);
    215             assert(Type::moved == 0);
    216             assert(t.value == 42);
    217         }
    218         assert(Type::count == 1);
    219         Type::reset();
    220         // Check getting Type by value from a non-const lvalue any.
    221         // This should cause the const copy constructor to be called.
    222         {
    223             Type t = any_cast<Type>(static_cast<any const&>(a));
    224 
    225             assert(Type::count == 2);
    226             assert(Type::copied == 1);
    227             assert(Type::const_copied == 1);
    228             assert(Type::non_const_copied == 0);
    229             assert(Type::moved == 0);
    230             assert(t.value == 42);
    231         }
    232         assert(Type::count == 1);
    233         Type::reset();
    234         // Check getting Type by value from a non-const rvalue any.
    235         // This should cause the non-const copy constructor to be called.
    236         {
    237             Type t = any_cast<Type>(static_cast<any &&>(a));
    238 
    239             assert(Type::count == 2);
    240             assert(Type::copied == 1);
    241             assert(Type::const_copied == 0);
    242             assert(Type::non_const_copied == 1);
    243             assert(Type::moved == 0);
    244             assert(t.value == 42);
    245         }
    246         assert(Type::count == 1);
    247         Type::reset();
    248         // Check getting const Type by value from a non-const rvalue any.
    249         // This should cause the const copy constructor to be called.
    250         {
    251             Type t = any_cast<Type const>(static_cast<any &&>(a));
    252 
    253             assert(Type::count == 2);
    254             assert(Type::copied == 1);
    255             assert(Type::const_copied == 1);
    256             assert(Type::non_const_copied == 0);
    257             assert(Type::moved == 0);
    258             assert(t.value == 42);
    259         }
    260         assert(Type::count == 1);
    261         Type::reset();
    262         // Check getting Type by value from a const rvalue any.
    263         // This should cause the const copy constructor to be called.
    264         {
    265             Type t = any_cast<Type>(static_cast<any const&&>(a));
    266 
    267             assert(Type::count == 2);
    268             assert(Type::copied == 1);
    269             assert(Type::const_copied == 1);
    270             assert(Type::non_const_copied == 0);
    271             assert(Type::moved == 0);
    272             assert(t.value == 42);
    273         }
    274         // Ensure we still only have 1 Type object alive.
    275         assert(Type::count == 1);
    276 
    277         // Check that the original object hasn't been changed.
    278         assertContains<Type>(a, 42);
    279     }
    280     assert(Type::count == 0);
    281 }
    282 
    283 // Even though you can't get a non-copyable class into std::any
    284 // the standard requires that these overloads compile and function.
    285 void test_non_copyable_ref() {
    286     struct no_copy
    287     {
    288         no_copy() {}
    289         no_copy(no_copy &&) {}
    290     private:
    291         no_copy(no_copy const &);
    292     };
    293 
    294     any a;
    295     checkThrows<no_copy &, no_copy const&>(a);
    296     checkThrows<no_copy const&>(a);
    297     assertEmpty(a);
    298 }
    299 
    300 int main() {
    301     test_cast_is_not_noexcept();
    302     test_cast_return_type();
    303     test_cast_empty();
    304     test_cast_to_reference<small>();
    305     test_cast_to_reference<large>();
    306     test_cast_to_value<small>();
    307     test_cast_to_value<large>();
    308     test_non_copyable_ref();
    309 }
    310