153 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 Value> any(Value &&)14 15// Test construction from a value.16// Concerns:17// ---------18// 1. The value is properly move/copied depending on the value category.19// 2. Both small and large values are properly handled.20 21 22#include <any>23#include <cassert>24 25#include "any_helpers.h"26#include "count_new.h"27#include "test_macros.h"28 29template <class Type>30void test_copy_value_throws()31{32#if !defined(TEST_HAS_NO_EXCEPTIONS)33 assert(Type::count == 0);34 {35 const Type t(42);36 assert(Type::count == 1);37 try {38 std::any a2 = t;39 assert(false);40 } catch (const my_any_exception&) {41 // do nothing42 } catch (...) {43 assert(false);44 }45 assert(Type::count == 1);46 assert(t.value == 42);47 }48 assert(Type::count == 0);49#endif50}51 52void test_move_value_throws()53{54#if !defined(TEST_HAS_NO_EXCEPTIONS)55 assert(throws_on_move::count == 0);56 {57 throws_on_move v;58 assert(throws_on_move::count == 1);59 try {60 std::any a = std::move(v);61 assert(false);62 } catch (const my_any_exception&) {63 // do nothing64 } catch (...) {65 assert(false);66 }67 assert(throws_on_move::count == 1);68 }69 assert(throws_on_move::count == 0);70#endif71}72 73template <class Type>74void test_copy_move_value() {75 // constructing from a small type should perform no allocations.76 DisableAllocationGuard g(isSmallType<Type>()); ((void)g);77 assert(Type::count == 0);78 Type::reset();79 {80 Type t(42);81 assert(Type::count == 1);82 83 std::any a = t;84 85 assert(Type::count == 2);86 assert(Type::copied == 1);87 assert(Type::moved == 0);88 assertContains<Type>(a, 42);89 }90 assert(Type::count == 0);91 Type::reset();92 {93 Type t(42);94 assert(Type::count == 1);95 96 std::any a = std::move(t);97 98 assert(Type::count == 2);99 assert(Type::copied == 0);100 assert(Type::moved == 1);101 assertContains<Type>(a, 42);102 }103}104 105// Test that any(ValueType&&) is *never* selected for a std::in_place_type_t specialization.106void test_sfinae_constraints() {107 using BadTag = std::in_place_type_t<int>;108 using OKTag = std::in_place_t;109 // Test that the tag type is properly handled in SFINAE110 BadTag t = std::in_place_type<int>;111 OKTag ot = std::in_place;112 {113 std::any a(t);114 assertContains<int>(a, 0);115 }116 {117 std::any a(std::move(t));118 assertContains<int>(a, 0);119 }120 {121 std::any a(ot);122 assert(containsType<OKTag>(a));123 }124 {125 struct Dummy { Dummy() = delete; };126 using T = std::in_place_type_t<Dummy>;127 static_assert(!std::is_constructible<std::any, T>::value, "");128 }129 {130 // Test that the ValueType&& constructor SFINAE's away when the131 // argument is non-copyable132 struct NoCopy {133 NoCopy() = default;134 NoCopy(NoCopy const&) = delete;135 NoCopy(int) {}136 };137 static_assert(!std::is_constructible<std::any, NoCopy>::value, "");138 static_assert(!std::is_constructible<std::any, NoCopy&>::value, "");139 static_assert(!std::is_convertible<NoCopy, std::any>::value, "");140 }141}142 143int main(int, char**) {144 test_copy_move_value<small>();145 test_copy_move_value<large>();146 test_copy_value_throws<small_throws_on_copy>();147 test_copy_value_throws<large_throws_on_copy>();148 test_move_value_throws();149 test_sfinae_constraints();150 151 return 0;152}153