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