| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any& operator=(any const &); | ||
|
|
||
| // Test copy assignment | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class LHS, class RHS> | ||
| void test_copy_assign() { | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| LHS::reset(); | ||
| RHS::reset(); | ||
| { | ||
| any lhs(LHS(1)); | ||
| any const rhs(RHS(2)); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 1); | ||
| assert(RHS::copied == 0); | ||
|
|
||
| lhs = rhs; | ||
|
|
||
| assert(RHS::copied == 1); | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 2); | ||
|
|
||
| assertContains<RHS>(lhs, 2); | ||
| assertContains<RHS>(rhs, 2); | ||
| } | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| } | ||
|
|
||
| template <class LHS> | ||
| void test_copy_assign_empty() { | ||
| assert(LHS::count == 0); | ||
| LHS::reset(); | ||
| { | ||
| any lhs; | ||
| any const rhs(LHS(42)); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(LHS::copied == 0); | ||
|
|
||
| lhs = rhs; | ||
|
|
||
| assert(LHS::copied == 1); | ||
| assert(LHS::count == 2); | ||
|
|
||
| assertContains<LHS>(lhs, 42); | ||
| assertContains<LHS>(rhs, 42); | ||
| } | ||
| assert(LHS::count == 0); | ||
| LHS::reset(); | ||
| { | ||
| any lhs(LHS(1)); | ||
| any const rhs; | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(LHS::copied == 0); | ||
|
|
||
| lhs = rhs; | ||
|
|
||
| assert(LHS::copied == 0); | ||
| assert(LHS::count == 0); | ||
|
|
||
| assertEmpty<LHS>(lhs); | ||
| assertEmpty(rhs); | ||
| } | ||
| assert(LHS::count == 0); | ||
| } | ||
|
|
||
| void test_copy_assign_self() { | ||
| // empty | ||
| { | ||
| any a; | ||
| a = a; | ||
| assertEmpty(a); | ||
| assert(globalMemCounter.checkOutstandingNewEq(0)); | ||
| } | ||
| assert(globalMemCounter.checkOutstandingNewEq(0)); | ||
| // small | ||
| { | ||
| any a((small(1))); | ||
| assert(small::count == 1); | ||
|
|
||
| a = a; | ||
|
|
||
| assert(small::count == 1); | ||
| assertContains<small>(a, 1); | ||
| assert(globalMemCounter.checkOutstandingNewEq(0)); | ||
| } | ||
| assert(small::count == 0); | ||
| assert(globalMemCounter.checkOutstandingNewEq(0)); | ||
| // large | ||
| { | ||
| any a(large(1)); | ||
| assert(large::count == 1); | ||
|
|
||
| a = a; | ||
|
|
||
| assert(large::count == 1); | ||
| assertContains<large>(a, 1); | ||
| assert(globalMemCounter.checkOutstandingNewEq(1)); | ||
| } | ||
| assert(large::count == 0); | ||
| assert(globalMemCounter.checkOutstandingNewEq(0)); | ||
| } | ||
|
|
||
| template <class Tp> | ||
| void test_copy_assign_throws() | ||
| { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| auto try_throw = | ||
| [](any& lhs, any const& rhs) { | ||
| try { | ||
| lhs = rhs; | ||
| assert(false); | ||
| } catch (my_any_exception const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| }; | ||
| // const lvalue to empty | ||
| { | ||
| any lhs; | ||
| any const rhs((Tp(1))); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(Tp::count == 1); | ||
| assertEmpty<Tp>(lhs); | ||
| assertContains<Tp>(rhs); | ||
| } | ||
| { | ||
| any lhs((small(2))); | ||
| any const rhs((Tp(1))); | ||
| assert(small::count == 1); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(small::count == 1); | ||
| assert(Tp::count == 1); | ||
| assertContains<small>(lhs, 2); | ||
| assertContains<Tp>(rhs); | ||
| } | ||
| { | ||
| any lhs((large(2))); | ||
| any const rhs((Tp(1))); | ||
| assert(large::count == 1); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(large::count == 1); | ||
| assert(Tp::count == 1); | ||
| assertContains<large>(lhs, 2); | ||
| assertContains<Tp>(rhs); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| int main() { | ||
| test_copy_assign<small1, small2>(); | ||
| test_copy_assign<large1, large2>(); | ||
| test_copy_assign<small, large>(); | ||
| test_copy_assign<large, small>(); | ||
| test_copy_assign_empty<small>(); | ||
| test_copy_assign_empty<large>(); | ||
| test_copy_assign_self(); | ||
| test_copy_assign_throws<small_throws_on_copy>(); | ||
| test_copy_assign_throws<large_throws_on_copy>(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any& operator=(any &&); | ||
|
|
||
| // Test move assignment. | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class LHS, class RHS> | ||
| void test_move_assign() { | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| { | ||
| LHS const s1(1); | ||
| any a(s1); | ||
| RHS const s2(2); | ||
| any a2(s2); | ||
|
|
||
| assert(LHS::count == 2); | ||
| assert(RHS::count == 2); | ||
|
|
||
| a = std::move(a2); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 2); | ||
|
|
||
| assertContains<RHS>(a, 2); | ||
| assertEmpty<RHS>(a2); | ||
| } | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| } | ||
|
|
||
| template <class LHS> | ||
| void test_move_assign_empty() { | ||
| assert(LHS::count == 0); | ||
| { | ||
| any a; | ||
| any a2((LHS(1))); | ||
|
|
||
| assert(LHS::count == 1); | ||
|
|
||
| a = std::move(a2); | ||
|
|
||
| assert(LHS::count == 1); | ||
|
|
||
| assertContains<LHS>(a, 1); | ||
| assertEmpty<LHS>(a2); | ||
| } | ||
| assert(LHS::count == 0); | ||
| { | ||
| any a((LHS(1))); | ||
| any a2; | ||
|
|
||
| assert(LHS::count == 1); | ||
|
|
||
| a = std::move(a2); | ||
|
|
||
| assert(LHS::count == 0); | ||
|
|
||
| assertEmpty<LHS>(a); | ||
| assertEmpty(a2); | ||
| } | ||
| assert(LHS::count == 0); | ||
| } | ||
|
|
||
| void test_move_assign_noexcept() { | ||
| any a1; | ||
| any a2; | ||
| static_assert( | ||
| noexcept(a1 = std::move(a2)) | ||
| , "any & operator=(any &&) must be noexcept" | ||
| ); | ||
| } | ||
|
|
||
| int main() { | ||
| test_move_assign_noexcept(); | ||
| test_move_assign<small1, small2>(); | ||
| test_move_assign<large1, large2>(); | ||
| test_move_assign<small, large>(); | ||
| test_move_assign<large, small>(); | ||
| test_move_assign_empty<small>(); | ||
| test_move_assign_empty<large>(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any& operator=(any const &); | ||
|
|
||
| // Test value copy and move assignment. | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class LHS, class RHS> | ||
| void test_assign_value() { | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| LHS::reset(); | ||
| RHS::reset(); | ||
| { | ||
| any lhs(LHS(1)); | ||
| any const rhs(RHS(2)); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 1); | ||
| assert(RHS::copied == 0); | ||
|
|
||
| lhs = rhs; | ||
|
|
||
| assert(RHS::copied == 1); | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 2); | ||
|
|
||
| assertContains<RHS>(lhs, 2); | ||
| assertContains<RHS>(rhs, 2); | ||
| } | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| LHS::reset(); | ||
| RHS::reset(); | ||
| { | ||
| any lhs(LHS(1)); | ||
| any rhs(RHS(2)); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 1); | ||
| assert(RHS::moved == 1); | ||
|
|
||
| lhs = std::move(rhs); | ||
|
|
||
| assert(RHS::moved >= 1); | ||
| assert(RHS::copied == 0); | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 1); | ||
|
|
||
| assertContains<RHS>(lhs, 2); | ||
| assertEmpty<RHS>(rhs); | ||
| } | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| } | ||
|
|
||
| template <class RHS> | ||
| void test_assign_value_empty() { | ||
| assert(RHS::count == 0); | ||
| RHS::reset(); | ||
| { | ||
| any lhs; | ||
| RHS rhs(42); | ||
| assert(RHS::count == 1); | ||
| assert(RHS::copied == 0); | ||
|
|
||
| lhs = rhs; | ||
|
|
||
| assert(RHS::count == 2); | ||
| assert(RHS::copied == 1); | ||
| assert(RHS::moved >= 0); | ||
| assertContains<RHS>(lhs, 42); | ||
| } | ||
| assert(RHS::count == 0); | ||
| RHS::reset(); | ||
| { | ||
| any lhs; | ||
| RHS rhs(42); | ||
| assert(RHS::count == 1); | ||
| assert(RHS::moved == 0); | ||
|
|
||
| lhs = std::move(rhs); | ||
|
|
||
| assert(RHS::count == 2); | ||
| assert(RHS::copied == 0); | ||
| assert(RHS::moved >= 1); | ||
| assertContains<RHS>(lhs, 42); | ||
| } | ||
| assert(RHS::count == 0); | ||
| RHS::reset(); | ||
| } | ||
|
|
||
|
|
||
| template <class Tp, bool Move = false> | ||
| void test_assign_throws() { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| auto try_throw= | ||
| [](any& lhs, auto&& rhs) { | ||
| try { | ||
| Move ? lhs = std::move(rhs) | ||
| : lhs = rhs; | ||
| assert(false); | ||
| } catch (my_any_exception const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| }; | ||
| // const lvalue to empty | ||
| { | ||
| any lhs; | ||
| Tp rhs(1); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(Tp::count == 1); | ||
| assertEmpty<Tp>(lhs); | ||
| } | ||
| { | ||
| any lhs((small(2))); | ||
| Tp rhs(1); | ||
| assert(small::count == 1); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(small::count == 1); | ||
| assert(Tp::count == 1); | ||
| assertContains<small>(lhs, 2); | ||
| } | ||
| { | ||
| any lhs((large(2))); | ||
| Tp rhs(1); | ||
| assert(large::count == 1); | ||
| assert(Tp::count == 1); | ||
|
|
||
| try_throw(lhs, rhs); | ||
|
|
||
| assert(large::count == 1); | ||
| assert(Tp::count == 1); | ||
| assertContains<large>(lhs, 2); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
|
|
||
| // Test that any& operator=(ValueType&&) is *never* selected for: | ||
| // * std::in_place type. | ||
| // * Non-copyable types | ||
| void test_sfinae_constraints() { | ||
| { | ||
| using Tag = std::in_place_type_t<int>; | ||
| using RawTag = std::remove_reference_t<Tag>; | ||
| static_assert(!std::is_assignable<std::any, RawTag&&>::value, ""); | ||
| } | ||
| { | ||
| struct Dummy { Dummy() = delete; }; | ||
| using T = std::in_place_type_t<Dummy>; | ||
| static_assert(!std::is_assignable<std::any, T>::value, ""); | ||
| } | ||
| { | ||
| // Test that the ValueType&& constructor SFINAE's away when the | ||
| // argument is non-copyable | ||
| struct NoCopy { | ||
| NoCopy() = default; | ||
| NoCopy(NoCopy const&) = delete; | ||
| NoCopy(NoCopy&&) = default; | ||
| }; | ||
| static_assert(!std::is_assignable<std::any, NoCopy>::value, ""); | ||
| } | ||
| } | ||
|
|
||
| int main() { | ||
| test_assign_value<small1, small2>(); | ||
| test_assign_value<large1, large2>(); | ||
| test_assign_value<small, large>(); | ||
| test_assign_value<large, small>(); | ||
| test_assign_value_empty<small>(); | ||
| test_assign_value_empty<large>(); | ||
| test_assign_throws<small_throws_on_copy>(); | ||
| test_assign_throws<large_throws_on_copy>(); | ||
| test_assign_throws<throws_on_move, /* Move = */ true>(); | ||
| test_sfinae_constraints(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any(any const &); | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class Type> | ||
| void test_copy_throws() { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| assert(Type::count == 0); | ||
| { | ||
| any const a((Type(42))); | ||
| assert(Type::count == 1); | ||
| try { | ||
| any const a2(a); | ||
| assert(false); | ||
| } catch (my_any_exception const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| assert(Type::count == 1); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| #endif | ||
| } | ||
|
|
||
| void test_copy_empty() { | ||
| DisableAllocationGuard g; ((void)g); // No allocations should occur. | ||
| any a1; | ||
| any a2(a1); | ||
|
|
||
| assertEmpty(a1); | ||
| assertEmpty(a2); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_copy() | ||
| { | ||
| // Copying small types should not perform any allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a((Type(42))); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
|
|
||
| any a2(a); | ||
|
|
||
| assert(Type::copied == 1); | ||
| assert(Type::count == 2); | ||
| assertContains<Type>(a, 42); | ||
| assertContains<Type>(a, 42); | ||
|
|
||
| // Modify a and check that a2 is unchanged | ||
| modifyValue<Type>(a, -1); | ||
| assertContains<Type>(a, -1); | ||
| assertContains<Type>(a2, 42); | ||
|
|
||
| // modify a2 and check that a is unchanged | ||
| modifyValue<Type>(a2, 999); | ||
| assertContains<Type>(a, -1); | ||
| assertContains<Type>(a2, 999); | ||
|
|
||
| // clear a and check that a2 is unchanged | ||
| a.reset(); | ||
| assertEmpty(a); | ||
| assertContains<Type>(a2, 999); | ||
| } | ||
| assert(Type::count == 0); | ||
| } | ||
|
|
||
| int main() { | ||
| test_copy<small>(); | ||
| test_copy<large>(); | ||
| test_copy_empty(); | ||
| test_copy_throws<small_throws_on_copy>(); | ||
| test_copy_throws<large_throws_on_copy>(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any() noexcept; | ||
|
|
||
| #include <any> | ||
| #include <type_traits> | ||
| #include <cassert> | ||
|
|
||
| #include "test_macros.h" | ||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
|
|
||
| #if TEST_HAS_BUILTIN_IDENTIFIER(__has_constant_initializer) | ||
| // std::any must have a constexpr default constructor, but it's a non-literal | ||
| // type so we can't create a constexpr variable. This tests that we actually | ||
| // get 'constant initialization'. | ||
| std::any a; | ||
| static_assert(__has_constant_initializer(a), | ||
| "any must be constant initializable"); | ||
| #endif | ||
|
|
||
| int main() | ||
| { | ||
| using std::any; | ||
| { | ||
| static_assert( | ||
| std::is_nothrow_default_constructible<any>::value | ||
| , "Must be default constructible" | ||
| ); | ||
| } | ||
| { | ||
| DisableAllocationGuard g; ((void)g); | ||
| any const a; | ||
| assertEmpty(a); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class T, class ...Args> any(in_place_type_t<T>, Args&&...); | ||
| // template <class T, class U, class ...Args> | ||
| // any(in_place_type_t<T>, initializer_list<U>, Args&&...); | ||
|
|
||
| // Test construction from a value. | ||
| // Concerns: | ||
| // --------- | ||
| // 1. The value is properly move/copied depending on the value category. | ||
| // 2. Both small and large values are properly handled. | ||
|
|
||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
| #include "test_convertible.hpp" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class Type> | ||
| void test_in_place_type() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Type>); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 0); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Type>, 101); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 101); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Type>, -1, 42, -1); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_in_place_type_tracked() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| { | ||
| any a(std::in_place<Type>); | ||
| assertArgsMatch<Type>(a); | ||
| } | ||
| { | ||
| any a(std::in_place<Type>, -1, 42, -1); | ||
| assertArgsMatch<Type, int, int, int>(a); | ||
| } | ||
| // initializer_list constructor tests | ||
| { | ||
| any a(std::in_place<Type>, {-1, 42, -1}); | ||
| assertArgsMatch<Type, std::initializer_list<int>>(a); | ||
| } | ||
| { | ||
| int x = 42; | ||
| any a(std::in_place<Type>, {-1, 42, -1}, x); | ||
| assertArgsMatch<Type, std::initializer_list<int>, int&>(a); | ||
| } | ||
| } | ||
|
|
||
| void test_ctor_sfinae() { | ||
| { | ||
| // Test that the init-list ctor SFINAE's away properly when | ||
| // construction would be ill-formed. | ||
| using IL = std::initializer_list<int>; | ||
| static_assert(!std::is_constructible<std::any, | ||
| std::in_place_type_t<int>, IL>::value, ""); | ||
| static_assert(std::is_constructible<std::any, | ||
| std::in_place_type_t<small_tracked_t>, IL>::value, ""); | ||
| } | ||
| { | ||
| // Test that the tagged dispatch constructor SFINAE's away when the | ||
| // argument is non-copyable | ||
| struct NoCopy { | ||
| NoCopy() = default; | ||
| NoCopy(NoCopy const&) = delete; | ||
| NoCopy(int) {} | ||
| NoCopy(std::initializer_list<int>, int) {} | ||
| }; | ||
| using Tag = std::in_place_type_t<NoCopy>; | ||
| using IL = std::initializer_list<int>; | ||
| static_assert(!std::is_constructible<std::any, Tag>::value, ""); | ||
| static_assert(!std::is_constructible<std::any, Tag, int>::value, ""); | ||
| static_assert(!std::is_constructible<std::any, Tag, IL, int>::value, ""); | ||
| } | ||
| } | ||
|
|
||
| struct Implicit { | ||
| Implicit(int) {} | ||
| Implicit(int, int, int) {} | ||
| Implicit(std::initializer_list<int>, int) {} | ||
| }; | ||
|
|
||
| void test_constructor_explicit() { | ||
| using I = Implicit; | ||
| using IT = std::in_place_type_t<I>; | ||
| static_assert(!test_convertible<std::any, IT, int>(), ""); | ||
| static_assert(std::is_constructible<std::any, IT, int>::value, ""); | ||
| static_assert(!test_convertible<std::any, IT, int, int, int>(), ""); | ||
| static_assert(std::is_constructible<std::any, IT, int, int, int>::value, ""); | ||
| static_assert(!test_convertible<std::any, IT, std::initializer_list<int>&, int>(), ""); | ||
| static_assert(std::is_constructible<std::any, IT, std::initializer_list<int>&, int>::value, ""); | ||
| } | ||
|
|
||
| int main() { | ||
| test_in_place_type<small>(); | ||
| test_in_place_type<large>(); | ||
| test_in_place_type<small_throws_on_copy>(); | ||
| test_in_place_type<large_throws_on_copy>(); | ||
| test_in_place_type<throws_on_move>(); | ||
| test_in_place_type_tracked<small_tracked_t>(); | ||
| test_in_place_type_tracked<large_tracked_t>(); | ||
| test_ctor_sfinae(); | ||
| test_constructor_explicit(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any(any &&) noexcept; | ||
|
|
||
| #include <any> | ||
| #include <utility> | ||
| #include <type_traits> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| // Moves are always noexcept. The throws_on_move object | ||
| // must be stored dynamically so the pointer is moved and | ||
| // not the stored object. | ||
| void test_move_does_not_throw() | ||
| { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| assert(throws_on_move::count == 0); | ||
| { | ||
| throws_on_move v(42); | ||
| any a(v); | ||
| assert(throws_on_move::count == 2); | ||
| // No allocations should be performed after this point. | ||
| DisableAllocationGuard g; ((void)g); | ||
| try { | ||
| any const a2(std::move(a)); | ||
| assertEmpty(a); | ||
| assertContains<throws_on_move>(a2, 42); | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| assert(throws_on_move::count == 1); | ||
| assertEmpty(a); | ||
| } | ||
| assert(throws_on_move::count == 0); | ||
| #endif | ||
| } | ||
|
|
||
| void test_move_empty() { | ||
| DisableAllocationGuard g; ((void)g); // no allocations should be performed. | ||
|
|
||
| any a1; | ||
| any a2(std::move(a1)); | ||
|
|
||
| assertEmpty(a1); | ||
| assertEmpty(a2); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_move() { | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a((Type(42))); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
|
|
||
| // Moving should not perform allocations since it must be noexcept. | ||
| DisableAllocationGuard g; ((void)g); | ||
|
|
||
| any a2(std::move(a)); | ||
|
|
||
| assert(Type::moved >= 1); // zero or more move operations can be performed. | ||
| assert(Type::copied == 0); // no copies can be performed. | ||
| assert(Type::count == 1); | ||
| assertEmpty(a); // Moves are always destructive. | ||
| assertContains<Type>(a2, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| } | ||
|
|
||
| int main() | ||
| { | ||
| // noexcept test | ||
| { | ||
| static_assert( | ||
| std::is_nothrow_move_constructible<any>::value | ||
| , "any must be nothrow move constructible" | ||
| ); | ||
| } | ||
| test_move<small>(); | ||
| test_move<large>(); | ||
| test_move_empty(); | ||
| test_move_does_not_throw(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class Value> any(Value &&) | ||
|
|
||
| // Test construction from a value. | ||
| // Concerns: | ||
| // --------- | ||
| // 1. The value is properly move/copied depending on the value category. | ||
| // 2. Both small and large values are properly handled. | ||
|
|
||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
|
|
||
| template <class Type> | ||
| void test_copy_value_throws() | ||
| { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| assert(Type::count == 0); | ||
| { | ||
| Type const t(42); | ||
| assert(Type::count == 1); | ||
| try { | ||
| any const a2(t); | ||
| assert(false); | ||
| } catch (my_any_exception const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| assert(Type::count == 1); | ||
| assert(t.value == 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| #endif | ||
| } | ||
|
|
||
| void test_move_value_throws() | ||
| { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| assert(throws_on_move::count == 0); | ||
| { | ||
| throws_on_move v; | ||
| assert(throws_on_move::count == 1); | ||
| try { | ||
| any const a(std::move(v)); | ||
| assert(false); | ||
| } catch (my_any_exception const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| assert(throws_on_move::count == 1); | ||
| } | ||
| assert(throws_on_move::count == 0); | ||
| #endif | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_copy_move_value() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| Type t(42); | ||
| assert(Type::count == 1); | ||
|
|
||
| any a(t); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| Type t(42); | ||
| assert(Type::count == 1); | ||
|
|
||
| any a(std::move(t)); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| } | ||
|
|
||
| void test_non_moveable_type() | ||
| { | ||
| using Type = deleted_move; | ||
| { | ||
| deleted_move mv(42); | ||
| std::any a(mv); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| deleted_move mv(42); | ||
| std::any a(std::move(mv)); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| } | ||
|
|
||
|
|
||
|
|
||
| // Test that any(ValueType&&) is *never* selected for a std::in_place type. | ||
| void test_sfinae_constraints() { | ||
| using Tag = std::in_place_type_t<int>; | ||
| #if defined(__clang__) | ||
| #pragma clang diagnostic push | ||
| #pragma clang diagnostic ignored "-Wignored-qualifiers" | ||
| #endif | ||
| static_assert(std::is_same<Tag, const Tag>::value, ""); | ||
| #if defined(__clang__) | ||
| #pragma clang diagnostic pop | ||
| #endif | ||
| // Test that the tag type is properly handled in SFINAE | ||
| Tag t = std::in_place; | ||
| { | ||
| std::any a(t); | ||
| assertContains<int>(a, 0); | ||
| } | ||
| { | ||
| std::any a(std::move(t)); | ||
| assertContains<int>(a, 0); | ||
| } | ||
| { | ||
| struct Dummy { Dummy() = delete; }; | ||
| using T = std::in_place_type_t<Dummy>; | ||
| static_assert(!std::is_constructible<std::any, T>::value, ""); | ||
| } | ||
| { | ||
| // Test that the ValueType&& constructor SFINAE's away when the | ||
| // argument is non-copyable | ||
| struct NoCopy { | ||
| NoCopy() = default; | ||
| NoCopy(NoCopy const&) = delete; | ||
| NoCopy(int) {} | ||
| }; | ||
| static_assert(!std::is_constructible<std::any, NoCopy>::value, ""); | ||
| static_assert(!std::is_convertible<NoCopy, std::any>::value, ""); | ||
| } | ||
| } | ||
|
|
||
| int main() { | ||
| test_copy_move_value<small>(); | ||
| test_copy_move_value<large>(); | ||
| test_copy_value_throws<small_throws_on_copy>(); | ||
| test_copy_value_throws<large_throws_on_copy>(); | ||
| test_move_value_throws(); | ||
| test_non_moveable_type(); | ||
| test_sfinae_constraints(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,255 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class T, class ...Args> emplace(Args&&...); | ||
| // template <class T, class U, class ...Args> | ||
| // void emplace(initializer_list<U>, Args&&...); | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| struct Tracked { | ||
| static int count; | ||
| Tracked() {++count;} | ||
| ~Tracked() { --count; } | ||
| }; | ||
| int Tracked::count = 0; | ||
|
|
||
| template <class Type> | ||
| void test_emplace_type() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
|
|
||
| a.emplace<Type>(); | ||
|
|
||
| assert(Tracked::count == 0); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 0); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
|
|
||
| a.emplace<Type>(101); | ||
|
|
||
| assert(Tracked::count == 0); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 101); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
|
|
||
| a.emplace<Type>(-1, 42, -1); | ||
|
|
||
| assert(Tracked::count == 0); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_emplace_type_tracked() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
| a.emplace<Type>(); | ||
| assert(Tracked::count == 0); | ||
| assertArgsMatch<Type>(a); | ||
| } | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
| a.emplace<Type>(-1, 42, -1); | ||
| assert(Tracked::count == 0); | ||
| assertArgsMatch<Type, int, int, int>(a); | ||
| } | ||
| // initializer_list constructor tests | ||
| { | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
| a.emplace<Type>({-1, 42, -1}); | ||
| assert(Tracked::count == 0); | ||
| assertArgsMatch<Type, std::initializer_list<int>>(a); | ||
| } | ||
| { | ||
| int x = 42; | ||
| any a(std::in_place<Tracked>); | ||
| assert(Tracked::count == 1); | ||
| a.emplace<Type>({-1, 42, -1}, x); | ||
| assert(Tracked::count == 0); | ||
| assertArgsMatch<Type, std::initializer_list<int>, int&>(a); | ||
| } | ||
| } | ||
|
|
||
| #ifndef TEST_HAS_NO_EXCEPTIONS | ||
|
|
||
| struct SmallThrows { | ||
| SmallThrows(int) { throw 42; } | ||
| SmallThrows(std::initializer_list<int>, int) { throw 42; } | ||
| }; | ||
| static_assert(IsSmallObject<SmallThrows>::value, ""); | ||
|
|
||
| struct LargeThrows { | ||
| LargeThrows(int) { throw 42; } | ||
| LargeThrows(std::initializer_list<int>, int) { throw 42; } | ||
| int data[10]; | ||
| }; | ||
| static_assert(!IsSmallObject<LargeThrows>::value, ""); | ||
|
|
||
| template <class Type> | ||
| void test_emplace_throws() | ||
| { | ||
| // any stores small type | ||
| { | ||
| std::any a(small{42}); | ||
| assert(small::count == 1); | ||
| try { | ||
| a.emplace<Type>(101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| assert(small::count == 0); | ||
| } | ||
| { | ||
| std::any a(small{42}); | ||
| assert(small::count == 1); | ||
| try { | ||
| a.emplace<Type>({1, 2, 3}, 101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| assert(small::count == 0); | ||
| } | ||
| // any stores large type | ||
| { | ||
| std::any a(large{42}); | ||
| assert(large::count == 1); | ||
| try { | ||
| a.emplace<Type>(101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| assert(large::count == 0); | ||
| } | ||
| { | ||
| std::any a(large{42}); | ||
| assert(large::count == 1); | ||
| try { | ||
| a.emplace<Type>({1, 2, 3}, 101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| assert(large::count == 0); | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
|
|
||
| template <class T, class ...Args> | ||
| constexpr auto has_emplace(int) | ||
| -> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; } | ||
|
|
||
| template <class ...Args> | ||
| constexpr bool has_emplace(long) { return false; } | ||
|
|
||
| template <class ...Args> | ||
| constexpr bool has_emplace() { return has_emplace<Args...>(0); } | ||
|
|
||
|
|
||
| template <class T, class IT, class ...Args> | ||
| constexpr auto has_emplace_init_list(int) | ||
| -> decltype(std::any{}.emplace<T>( | ||
| {std::declval<IT>(), std::declval<IT>(), std::declval<IT>()}, | ||
| std::declval<Args>()...), true) { return true; } | ||
|
|
||
| template <class ...Args> | ||
| constexpr bool has_emplace_init_list(long) { return false; } | ||
|
|
||
| template <class ...Args> | ||
| constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); } | ||
|
|
||
|
|
||
| void test_emplace_sfinae_constraints() { | ||
| { | ||
| static_assert(has_emplace<int>(), ""); | ||
| static_assert(has_emplace<int, int>(), ""); | ||
| static_assert(!has_emplace<int, int, int>(), "not constructible"); | ||
| static_assert(!has_emplace_init_list<int, int>(), "not constructible from il"); | ||
| } | ||
| { | ||
| static_assert(has_emplace<small>(), ""); | ||
| static_assert(has_emplace<large>(), ""); | ||
| static_assert(!has_emplace<small, void*>(), ""); | ||
| static_assert(!has_emplace<large, void*>(), ""); | ||
|
|
||
| static_assert(has_emplace_init_list<small, int>(), ""); | ||
| static_assert(has_emplace_init_list<large, int>(), ""); | ||
| static_assert(!has_emplace_init_list<small, void*>(), ""); | ||
| static_assert(!has_emplace_init_list<large, void*>(), ""); | ||
| } | ||
| { | ||
| // Test that the emplace SFINAE's away when the | ||
| // argument is non-copyable | ||
| struct NoCopy { | ||
| NoCopy() = default; | ||
| NoCopy(NoCopy const&) = delete; | ||
| NoCopy(int) {} | ||
| NoCopy(std::initializer_list<int>, int, int) {} | ||
| }; | ||
| static_assert(!has_emplace<NoCopy>(), ""); | ||
| static_assert(!has_emplace<NoCopy, int>(), ""); | ||
| static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), ""); | ||
| } | ||
| } | ||
|
|
||
| int main() { | ||
| test_emplace_type<small>(); | ||
| test_emplace_type<large>(); | ||
| test_emplace_type<small_throws_on_copy>(); | ||
| test_emplace_type<large_throws_on_copy>(); | ||
| test_emplace_type<throws_on_move>(); | ||
| test_emplace_type_tracked<small_tracked_t>(); | ||
| test_emplace_type_tracked<large_tracked_t>(); | ||
| test_emplace_sfinae_constraints(); | ||
| #ifndef TEST_HAS_NO_EXCEPTIONS | ||
| test_emplace_throws<SmallThrows>(); | ||
| test_emplace_throws<LargeThrows>(); | ||
| #endif | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any::reset() noexcept | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
|
|
||
| int main() | ||
| { | ||
| using std::any; | ||
| using std::any_cast; | ||
| // empty | ||
| { | ||
| any a; | ||
|
|
||
| // noexcept check | ||
| static_assert( | ||
| noexcept(a.reset()) | ||
| , "any.reset() must be noexcept" | ||
| ); | ||
|
|
||
| assertEmpty(a); | ||
|
|
||
| a.reset(); | ||
|
|
||
| assertEmpty(a); | ||
| } | ||
| // small object | ||
| { | ||
| any a((small(1))); | ||
| assert(small::count == 1); | ||
| assertContains<small>(a, 1); | ||
|
|
||
| a.reset(); | ||
|
|
||
| assertEmpty<small>(a); | ||
| assert(small::count == 0); | ||
| } | ||
| // large object | ||
| { | ||
| any a(large(1)); | ||
| assert(large::count == 1); | ||
| assertContains<large>(a); | ||
|
|
||
| a.reset(); | ||
|
|
||
| assertEmpty<large>(a); | ||
| assert(large::count == 0); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any::swap(any &) noexcept | ||
|
|
||
| // Test swap(large, small) and swap(small, large) | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| template <class LHS, class RHS> | ||
| void test_swap() { | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| { | ||
| any a1((LHS(1))); | ||
| any a2(RHS{2}); | ||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 1); | ||
|
|
||
| a1.swap(a2); | ||
|
|
||
| assert(LHS::count == 1); | ||
| assert(RHS::count == 1); | ||
|
|
||
| assertContains<RHS>(a1, 2); | ||
| assertContains<LHS>(a2, 1); | ||
| } | ||
| assert(LHS::count == 0); | ||
| assert(RHS::count == 0); | ||
| assert(LHS::copied == 0); | ||
| assert(RHS::copied == 0); | ||
| } | ||
|
|
||
| template <class Tp> | ||
| void test_swap_empty() { | ||
| assert(Tp::count == 0); | ||
| { | ||
| any a1((Tp(1))); | ||
| any a2; | ||
| assert(Tp::count == 1); | ||
|
|
||
| a1.swap(a2); | ||
|
|
||
| assert(Tp::count == 1); | ||
|
|
||
| assertContains<Tp>(a2, 1); | ||
| assertEmpty(a1); | ||
| } | ||
| assert(Tp::count == 0); | ||
| { | ||
| any a1((Tp(1))); | ||
| any a2; | ||
| assert(Tp::count == 1); | ||
|
|
||
| a2.swap(a1); | ||
|
|
||
| assert(Tp::count == 1); | ||
|
|
||
| assertContains<Tp>(a2, 1); | ||
| assertEmpty(a1); | ||
| } | ||
| assert(Tp::count == 0); | ||
| assert(Tp::copied == 0); | ||
| } | ||
|
|
||
| void test_noexcept() | ||
| { | ||
| any a1; | ||
| any a2; | ||
| static_assert( | ||
| noexcept(a1.swap(a2)) | ||
| , "any::swap(any&) must be noexcept" | ||
| ); | ||
| } | ||
|
|
||
| int main() | ||
| { | ||
| test_noexcept(); | ||
| test_swap_empty<small>(); | ||
| test_swap_empty<large>(); | ||
| test_swap<small1, small2>(); | ||
| test_swap<large1, large2>(); | ||
| test_swap<small, large>(); | ||
| test_swap<large, small>(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // any::has_value() noexcept | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
|
|
||
| int main() | ||
| { | ||
| using std::any; | ||
| // noexcept test | ||
| { | ||
| any a; | ||
| static_assert(noexcept(a.has_value()), "any::has_value() must be noexcept"); | ||
| } | ||
| // empty | ||
| { | ||
| any a; | ||
| assert(!a.has_value()); | ||
|
|
||
| a.reset(); | ||
| assert(!a.has_value()); | ||
|
|
||
| a = 42; | ||
| assert(a.has_value()); | ||
| } | ||
| // small object | ||
| { | ||
| small const s(1); | ||
| any a(s); | ||
| assert(a.has_value()); | ||
|
|
||
| a.reset(); | ||
| assert(!a.has_value()); | ||
|
|
||
| a = s; | ||
| assert(a.has_value()); | ||
| } | ||
| // large object | ||
| { | ||
| large const l(1); | ||
| any a(l); | ||
| assert(a.has_value()); | ||
|
|
||
| a.reset(); | ||
| assert(!a.has_value()); | ||
|
|
||
| a = l; | ||
| assert(a.has_value()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // XFAIL: libcpp-no-rtti | ||
|
|
||
| // <any> | ||
|
|
||
| // any::type() noexcept | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
| #include "any_helpers.h" | ||
|
|
||
| int main() | ||
| { | ||
| using std::any; | ||
| { | ||
| any const a; | ||
| assert(a.type() == typeid(void)); | ||
| static_assert(noexcept(a.type()), "any::type() must be noexcept"); | ||
| } | ||
| { | ||
| small const s(1); | ||
| any const a(s); | ||
| assert(a.type() == typeid(small)); | ||
|
|
||
| } | ||
| { | ||
| large const l(1); | ||
| any const a(l); | ||
| assert(a.type() == typeid(large)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // [Note any is a not a literal type --end note] | ||
|
|
||
| #include <any> | ||
| #include <type_traits> | ||
|
|
||
| int main () { | ||
| static_assert(!std::is_literal_type<std::any>::value, ""); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class ValueType> | ||
| // ValueType const* any_cast(any const *) noexcept; | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType * any_cast(any *) noexcept; | ||
|
|
||
| #include <any> | ||
| #include <type_traits> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| // Test that the operators are properly noexcept. | ||
| void test_cast_is_noexcept() { | ||
| any a; | ||
| static_assert(noexcept(any_cast<int>(&a)), ""); | ||
|
|
||
| any const& ca = a; | ||
| static_assert(noexcept(any_cast<int>(&ca)), ""); | ||
| } | ||
|
|
||
| // Test that the return type of any_cast is correct. | ||
| void test_cast_return_type() { | ||
| any a; | ||
| static_assert(std::is_same<decltype(any_cast<int>(&a)), int*>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const>(&a)), int const*>::value, ""); | ||
|
|
||
| any const& ca = a; | ||
| static_assert(std::is_same<decltype(any_cast<int>(&ca)), int const*>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const>(&ca)), int const*>::value, ""); | ||
| } | ||
|
|
||
| // Test that any_cast handles null pointers. | ||
| void test_cast_nullptr() { | ||
| any* a = nullptr; | ||
| assert(nullptr == any_cast<int>(a)); | ||
| assert(nullptr == any_cast<int const>(a)); | ||
|
|
||
| any const* ca = nullptr; | ||
| assert(nullptr == any_cast<int>(ca)); | ||
| assert(nullptr == any_cast<int const>(ca)); | ||
| } | ||
|
|
||
| // Test casting an empty object. | ||
| void test_cast_empty() { | ||
| { | ||
| any a; | ||
| assert(nullptr == any_cast<int>(&a)); | ||
| assert(nullptr == any_cast<int const>(&a)); | ||
|
|
||
| any const& ca = a; | ||
| assert(nullptr == any_cast<int>(&ca)); | ||
| assert(nullptr == any_cast<int const>(&ca)); | ||
| } | ||
| // Create as non-empty, then make empty and run test. | ||
| { | ||
| any a(42); | ||
| a.reset(); | ||
| assert(nullptr == any_cast<int>(&a)); | ||
| assert(nullptr == any_cast<int const>(&a)); | ||
|
|
||
| any const& ca = a; | ||
| assert(nullptr == any_cast<int>(&ca)); | ||
| assert(nullptr == any_cast<int const>(&ca)); | ||
| } | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_cast() { | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a((Type(42))); | ||
| any const& ca = a; | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
|
|
||
| // Try a cast to a bad type. | ||
| // NOTE: Type cannot be an int. | ||
| assert(any_cast<int>(&a) == nullptr); | ||
| assert(any_cast<int const>(&a) == nullptr); | ||
| assert(any_cast<int const volatile>(&a) == nullptr); | ||
|
|
||
| // Try a cast to the right type, but as a pointer. | ||
| assert(any_cast<Type*>(&a) == nullptr); | ||
| assert(any_cast<Type const*>(&a) == nullptr); | ||
|
|
||
| // Check getting a unqualified type from a non-const any. | ||
| Type* v = any_cast<Type>(&a); | ||
| assert(v != nullptr); | ||
| assert(v->value == 42); | ||
|
|
||
| // change the stored value and later check for the new value. | ||
| v->value = 999; | ||
|
|
||
| // Check getting a const qualified type from a non-const any. | ||
| Type const* cv = any_cast<Type const>(&a); | ||
| assert(cv != nullptr); | ||
| assert(cv == v); | ||
| assert(cv->value == 999); | ||
|
|
||
| // Check getting a unqualified type from a const any. | ||
| cv = any_cast<Type>(&ca); | ||
| assert(cv != nullptr); | ||
| assert(cv == v); | ||
| assert(cv->value == 999); | ||
|
|
||
| // Check getting a const-qualified type from a const any. | ||
| cv = any_cast<Type const>(&ca); | ||
| assert(cv != nullptr); | ||
| assert(cv == v); | ||
| assert(cv->value == 999); | ||
|
|
||
| // Check that no more objects were created, copied or moved. | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
| } | ||
| assert(Type::count == 0); | ||
| } | ||
|
|
||
| void test_cast_non_copyable_type() | ||
| { | ||
| // Even though 'any' never stores non-copyable types | ||
| // we still need to support any_cast<NoCopy>(ptr) | ||
| struct NoCopy { NoCopy(NoCopy const&) = delete; }; | ||
| std::any a(42); | ||
| std::any const& ca = a; | ||
| assert(std::any_cast<NoCopy>(&a) == nullptr); | ||
| assert(std::any_cast<NoCopy>(&ca) == nullptr); | ||
| } | ||
|
|
||
| int main() { | ||
| test_cast_is_noexcept(); | ||
| test_cast_return_type(); | ||
| test_cast_nullptr(); | ||
| test_cast_empty(); | ||
| test_cast<small>(); | ||
| test_cast<large>(); | ||
| test_cast_non_copyable_type(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,396 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class ValueType> | ||
| // ValueType const any_cast(any const&); | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType any_cast(any &); | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType any_cast(any &&); | ||
|
|
||
| #include <any> | ||
| #include <type_traits> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
| using std::bad_any_cast; | ||
|
|
||
|
|
||
| // Test that the operators are NOT marked noexcept. | ||
| void test_cast_is_not_noexcept() { | ||
| any a; | ||
| static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), ""); | ||
| static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), ""); | ||
| static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), ""); | ||
| } | ||
|
|
||
| // Test that the return type of any_cast is correct. | ||
| void test_cast_return_type() { | ||
| any a; | ||
| static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, ""); | ||
|
|
||
| static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, ""); | ||
|
|
||
| static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, ""); | ||
|
|
||
| static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, ""); | ||
|
|
||
| any const& ca = a; | ||
| static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, ""); | ||
| static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, ""); | ||
|
|
||
| static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, ""); | ||
| } | ||
|
|
||
| template <class Type, class ConstT = Type> | ||
| void checkThrows(any& a) | ||
| { | ||
| #if !defined(TEST_HAS_NO_EXCEPTIONS) | ||
| try { | ||
| any_cast<Type>(a); | ||
| assert(false); | ||
| } catch (bad_any_cast const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
|
|
||
| try { | ||
| any_cast<ConstT>(static_cast<any const&>(a)); | ||
| assert(false); | ||
| } catch (bad_any_cast const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
|
|
||
| try { | ||
| any_cast<Type>(static_cast<any&&>(a)); | ||
| assert(false); | ||
| } catch (bad_any_cast const &) { | ||
| // do nothing | ||
| } catch (...) { | ||
| assert(false); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| void test_cast_empty() { | ||
| // None of these operations should allocate. | ||
| DisableAllocationGuard g; ((void)g); | ||
| any a; | ||
| checkThrows<int>(a); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_cast_to_reference() { | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a((Type(42))); | ||
| any const& ca = a; | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
|
|
||
| // Try a cast to a bad type. | ||
| // NOTE: Type cannot be an int. | ||
| checkThrows<int>(a); | ||
| checkThrows<int&, int const&>(a); | ||
| checkThrows<Type*, Type const*>(a); | ||
| checkThrows<Type const*>(a); | ||
|
|
||
| // Check getting a type by reference from a non-const lvalue any. | ||
| { | ||
| Type& v = any_cast<Type&>(a); | ||
| assert(v.value == 42); | ||
|
|
||
| Type const &cv = any_cast<Type const&>(a); | ||
| assert(&cv == &v); | ||
| } | ||
| // Check getting a type by reference from a const lvalue any. | ||
| { | ||
| Type const& v = any_cast<Type const&>(ca); | ||
| assert(v.value == 42); | ||
|
|
||
| Type const &cv = any_cast<Type const&>(ca); | ||
| assert(&cv == &v); | ||
| } | ||
| // Check getting a type by reference from a non-const rvalue | ||
| { | ||
| Type& v = any_cast<Type&>(std::move(a)); | ||
| assert(v.value == 42); | ||
|
|
||
| Type const &cv = any_cast<Type const&>(std::move(a)); | ||
| assert(&cv == &v); | ||
| } | ||
| // Check getting a type by reference from a const rvalue any. | ||
| { | ||
| Type const& v = any_cast<Type const&>(std::move(ca)); | ||
| assert(v.value == 42); | ||
|
|
||
| Type const &cv = any_cast<Type const&>(std::move(ca)); | ||
| assert(&cv == &v); | ||
| } | ||
| // Check getting a type by reference from a const rvalue any. | ||
| { | ||
| Type&& v = any_cast<Type&&>(std::move(a)); | ||
| assert(v.value == 42); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
|
|
||
| Type&& cv = any_cast<Type&&>(std::move(a)); | ||
| assert(&cv == &v); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
| } | ||
| // Check getting a type by reference from a const rvalue any. | ||
| { | ||
| Type const&& v = any_cast<Type const&&>(std::move(a)); | ||
| assert(v.value == 42); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
|
|
||
| Type const&& cv = any_cast<Type const&&>(std::move(a)); | ||
| assert(&cv == &v); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
| } | ||
| // Check that the original object hasn't been changed. | ||
| assertContains<Type>(a, 42); | ||
|
|
||
| // Check that no objects have been created/copied/moved. | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
| } | ||
| assert(Type::count == 0); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_cast_to_value() { | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a((Type(42))); | ||
| any const& ca = a; | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 1); | ||
|
|
||
| // Try a cast to a bad type. | ||
| // NOTE: Type cannot be an int. | ||
| checkThrows<int>(a); | ||
| checkThrows<int&, int const&>(a); | ||
| checkThrows<Type*, Type const*>(a); | ||
| checkThrows<Type const*>(a); | ||
|
|
||
| Type::reset(); // NOTE: reset does not modify Type::count | ||
| // Check getting Type by value from a non-const lvalue any. | ||
| // This should cause the non-const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type>(a); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::const_copied == 0); | ||
| assert(Type::non_const_copied == 1); | ||
| assert(Type::moved == 0); | ||
| assert(t.value == 42); | ||
| } | ||
| assert(Type::count == 1); | ||
| Type::reset(); | ||
| // Check getting const Type by value from a non-const lvalue any. | ||
| // This should cause the const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type const>(a); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::const_copied == 1); | ||
| assert(Type::non_const_copied == 0); | ||
| assert(Type::moved == 0); | ||
| assert(t.value == 42); | ||
| } | ||
| assert(Type::count == 1); | ||
| Type::reset(); | ||
| // Check getting Type by value from a non-const lvalue any. | ||
| // This should cause the const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type>(static_cast<any const&>(a)); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::const_copied == 1); | ||
| assert(Type::non_const_copied == 0); | ||
| assert(Type::moved == 0); | ||
| assert(t.value == 42); | ||
| } | ||
| assert(Type::count == 1); | ||
| Type::reset(); | ||
| // Check getting Type by value from a non-const rvalue any. | ||
| // This should cause the non-const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type>(static_cast<any &&>(a)); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::moved == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::const_copied == 0); | ||
| assert(Type::non_const_copied == 0); | ||
| assert(t.value == 42); | ||
| assert(any_cast<Type&>(a).value == 0); | ||
| any_cast<Type&>(a).value = 42; // reset the value | ||
| } | ||
| assert(Type::count == 1); | ||
| Type::reset(); | ||
| // Check getting const Type by value from a non-const rvalue any. | ||
| // This should cause the const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type const>(static_cast<any &&>(a)); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::const_copied == 1); | ||
| assert(Type::non_const_copied == 0); | ||
| assert(Type::moved == 0); | ||
| assert(t.value == 42); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
| } | ||
| assert(Type::count == 1); | ||
| Type::reset(); | ||
| // Check getting Type by value from a const rvalue any. | ||
| // This should cause the const copy constructor to be called. | ||
| { | ||
| Type t = any_cast<Type>(static_cast<any const&&>(a)); | ||
|
|
||
| assert(Type::count == 2); | ||
| assert(Type::copied == 1); | ||
| assert(Type::const_copied == 1); | ||
| assert(Type::non_const_copied == 0); | ||
| assert(Type::moved == 0); | ||
| assert(t.value == 42); | ||
| assert(any_cast<Type&>(a).value == 42); | ||
| } | ||
| // Ensure we still only have 1 Type object alive. | ||
| assert(Type::count == 1); | ||
|
|
||
| // Check that the original object hasn't been changed. | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| } | ||
|
|
||
| void test_cast_to_value_deleted_move() | ||
| { | ||
| using Type = deleted_move; | ||
| { | ||
| std::any a(deleted_move(42)); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
|
|
||
| Type const& t = any_cast<Type>(a); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 2); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| std::any a(deleted_move(42)); | ||
| std::any const& ca = a; | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
|
|
||
| Type const& t = any_cast<Type>(ca); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 2); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| std::any a(deleted_move(42)); | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
|
|
||
| Type&& t = any_cast<Type>(std::move(a)); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 2); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| std::any a(deleted_move(42)); | ||
| std::any const& ca = a; | ||
| assert(Type::count == 1); | ||
| assert(Type::copied == 1); | ||
| assert(Type::moved == 0); | ||
|
|
||
| Type&& t = any_cast<Type>(std::move(ca)); | ||
| assert(Type::count == 2); | ||
| assert(Type::copied == 2); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| } | ||
|
|
||
| // Even though you can't get a non-copyable class into std::any | ||
| // the standard requires that these overloads compile and function. | ||
| void test_non_copyable_ref() { | ||
| struct no_copy | ||
| { | ||
| no_copy() {} | ||
| no_copy(no_copy &&) {} | ||
| private: | ||
| no_copy(no_copy const &); | ||
| }; | ||
|
|
||
| any a; | ||
| checkThrows<no_copy &, no_copy const&>(a); | ||
| checkThrows<no_copy const&>(a); | ||
| assertEmpty(a); | ||
| } | ||
|
|
||
| int main() { | ||
| test_cast_is_not_noexcept(); | ||
| test_cast_return_type(); | ||
| test_cast_empty(); | ||
| test_cast_to_reference<small>(); | ||
| test_cast_to_reference<large>(); | ||
| test_cast_to_value<small>(); | ||
| test_cast_to_value<large>(); | ||
| test_cast_to_value_deleted_move(); | ||
| test_non_copyable_ref(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class ValueType> | ||
| // ValueType any_cast(any const &); | ||
|
|
||
| // Try and cast away const. | ||
|
|
||
| #include <any> | ||
|
|
||
| struct TestType {}; | ||
| struct TestType2 {}; | ||
|
|
||
| int main() | ||
| { | ||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| any a; | ||
|
|
||
| // expected-error@any:* 2 {{binding value of type '_Tp' (aka 'const TestType') to reference to type 'TestType' drops 'const' qualifier}} | ||
| any_cast<TestType &>(static_cast<any const&>(a)); // expected-note {{requested here}} | ||
| any_cast<TestType &&>(static_cast<any const&>(a)); // expected-note {{requested here}} | ||
|
|
||
| // expected-error@any:* 2 {{binding value of type '_Tp' (aka 'const TestType2') to reference to type 'TestType2' drops 'const' qualifier}} | ||
| any_cast<TestType2 &>(static_cast<any const&&>(a)); // expected-note {{requested here}} | ||
| any_cast<TestType2 &&>(static_cast<any const&&>(a)); // expected-note {{requested here}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class ValueType> | ||
| // ValueType const any_cast(any const&); | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType any_cast(any &); | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType any_cast(any &&); | ||
|
|
||
| // Test instantiating the any_cast with a non-copyable type. | ||
|
|
||
| #include <any> | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| struct no_copy | ||
| { | ||
| no_copy() {} | ||
| no_copy(no_copy &&) {} | ||
| private: | ||
| no_copy(no_copy const &); | ||
| }; | ||
|
|
||
| int main() { | ||
| any a; | ||
| any_cast<no_copy>(static_cast<any&>(a)); // expected-note {{requested here}} | ||
| any_cast<no_copy>(static_cast<any const&>(a)); // expected-note {{requested here}} | ||
| any_cast<no_copy>(static_cast<any &&>(a)); // expected-note {{requested here}} | ||
| // expected-error@any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}} | ||
| // expected-error@any:* 2 {{calling a private constructor of class 'no_copy'}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class ValueType> | ||
| // ValueType const* any_cast(any const *) noexcept; | ||
| // | ||
| // template <class ValueType> | ||
| // ValueType * any_cast(any *) noexcept; | ||
|
|
||
| #include <any> | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| int main() | ||
| { | ||
| any a(1); | ||
| any_cast<int &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int &&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int const &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int const&&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any const& a2 = a; | ||
| any_cast<int &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int const &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| any_cast<int const &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // template <class T, class ...Args> any make_any(Args&&...); | ||
| // template <class T, class U, class ...Args> | ||
| // any make_any(initializer_list<U>, Args&&...); | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| #include "any_helpers.h" | ||
| #include "count_new.hpp" | ||
| #include "test_macros.h" | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
|
|
||
| template <class Type> | ||
| void test_make_any_type() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a = std::make_any<Type>(); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 0); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a = std::make_any<Type>(101); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 101); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| { | ||
| any a = std::make_any<Type>(-1, 42, -1); | ||
|
|
||
| assert(Type::count == 1); | ||
| assert(Type::copied == 0); | ||
| assert(Type::moved == 0); | ||
| assertContains<Type>(a, 42); | ||
| } | ||
| assert(Type::count == 0); | ||
| Type::reset(); | ||
| } | ||
|
|
||
| template <class Type> | ||
| void test_make_any_type_tracked() { | ||
| // constructing from a small type should perform no allocations. | ||
| DisableAllocationGuard g(isSmallType<Type>()); ((void)g); | ||
| { | ||
| any a = std::make_any<Type>(); | ||
| assertArgsMatch<Type>(a); | ||
| } | ||
| { | ||
| any a = std::make_any<Type>(-1, 42, -1); | ||
| assertArgsMatch<Type, int, int, int>(a); | ||
| } | ||
| // initializer_list constructor tests | ||
| { | ||
| any a = std::make_any<Type>({-1, 42, -1}); | ||
| assertArgsMatch<Type, std::initializer_list<int>>(a); | ||
| } | ||
| { | ||
| int x = 42; | ||
| any a = std::make_any<Type>({-1, 42, -1}, x); | ||
| assertArgsMatch<Type, std::initializer_list<int>, int&>(a); | ||
| } | ||
| } | ||
|
|
||
| #ifndef TEST_HAS_NO_EXCEPTIONS | ||
|
|
||
| struct SmallThrows { | ||
| SmallThrows(int) { throw 42; } | ||
| SmallThrows(std::initializer_list<int>, int) { throw 42; } | ||
| }; | ||
| static_assert(IsSmallObject<SmallThrows>::value, ""); | ||
|
|
||
| struct LargeThrows { | ||
| LargeThrows(int) { throw 42; } | ||
| LargeThrows(std::initializer_list<int>, int) { throw 42; } | ||
| int data[10]; | ||
| }; | ||
| static_assert(!IsSmallObject<LargeThrows>::value, ""); | ||
|
|
||
| template <class Type> | ||
| void test_make_any_throws() | ||
| { | ||
| { | ||
| try { | ||
| std::make_any<Type>(101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| } | ||
| { | ||
| try { | ||
| std::make_any<Type>({1, 2, 3}, 101); | ||
| assert(false); | ||
| } catch (int const&) { | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
|
|
||
| int main() { | ||
| test_make_any_type<small>(); | ||
| test_make_any_type<large>(); | ||
| test_make_any_type<small_throws_on_copy>(); | ||
| test_make_any_type<large_throws_on_copy>(); | ||
| test_make_any_type<throws_on_move>(); | ||
| test_make_any_type_tracked<small_tracked_t>(); | ||
| test_make_any_type_tracked<large_tracked_t>(); | ||
| #ifndef TEST_HAS_NO_EXCEPTIONS | ||
| test_make_any_throws<SmallThrows>(); | ||
| test_make_any_throws<LargeThrows>(); | ||
|
|
||
| #endif | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is dual licensed under the MIT and the University of Illinois Open | ||
| // Source Licenses. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++98, c++03, c++11, c++14 | ||
|
|
||
| // <any> | ||
|
|
||
| // void swap(any &, any &) noexcept | ||
|
|
||
| // swap(...) just wraps any::swap(...). That function is tested elsewhere. | ||
|
|
||
| #include <any> | ||
| #include <cassert> | ||
|
|
||
| using std::any; | ||
| using std::any_cast; | ||
|
|
||
| int main() | ||
| { | ||
|
|
||
| { // test noexcept | ||
| any a; | ||
| static_assert(noexcept(swap(a, a)), "swap(any&, any&) must be noexcept"); | ||
| } | ||
| { | ||
| any a1(1); | ||
| any a2(2); | ||
|
|
||
| swap(a1, a2); | ||
|
|
||
| assert(any_cast<int>(a1) == 2); | ||
| assert(any_cast<int>(a2) == 1); | ||
| } | ||
| } |