//===----------------------------------------------------------------------===// // // 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); } } // Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization. void test_sfinae_constraints() { using BadTag = std::in_place_type_t; using OKTag = std::in_place_t; // Test that the tag type is properly handled in SFINAE BadTag t = std::in_place_type; OKTag ot = std::in_place; { std::any a(t); assertContains(a, 0); } { std::any a(std::move(t)); assertContains(a, 0); } { std::any a(ot); assert(containsType(a)); } { 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_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_sfinae_constraints(); }