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