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-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14
10
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 nothing
42 } catch (...) {
43 assert(false);
44 }
45 assert(Type::count == 1);
46 assert(t.value == 42);
47 }
48 assert(Type::count == 0);
49#endif
50}
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 nothing
64 } catch (...) {
65 assert(false);
66 }
67 assert(throws_on_move::count == 1);
68 }
69 assert(throws_on_move::count == 0);
70#endif
71}
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 SFINAE
110 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 the
131 // argument is non-copyable
132 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

source code of libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp