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
29 template <class Type>
test_copy_value_throws()30 void 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
test_move_value_throws()52 void 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
73 template <class Type>
test_copy_move_value()74 void 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.
test_sfinae_constraints()106 void 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
main(int,char **)143 int 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