xref: /llvm-project/libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp (revision ec350ad418a24f70c88758259c774a1e11c06d74)
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