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> |
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 | |
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> |
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. |
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 | |
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 | |