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