brintos

brintos / llvm-project-archived public Read only

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