//===----------------------------------------------------------------------===// // // 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 // // template 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 #include #include "any_helpers.h" #include "count_new.hpp" #include "test_macros.h" using std::any; using std::any_cast; template 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 void test_copy_move_value() { // constructing from a small type should perform no allocations. DisableAllocationGuard g(isSmallType()); ((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(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(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(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(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; #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wignored-qualifiers" #endif static_assert(std::is_same::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(a, 0); } { std::any a(std::move(t)); assertContains(a, 0); } { struct Dummy { Dummy() = delete; }; using T = std::in_place_type_t; static_assert(!std::is_constructible::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::value, ""); static_assert(!std::is_convertible::value, ""); } } int main() { test_copy_move_value(); test_copy_move_value(); test_copy_value_throws(); test_copy_value_throws(); test_move_value_throws(); test_non_moveable_type(); test_sfinae_constraints(); }