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 |
10 | |
11 | // <tuple> |
12 | |
13 | // See https://llvm.org/PR20855. |
14 | |
15 | #include <functional> |
16 | #include <tuple> |
17 | #include <string> |
18 | #include <cassert> |
19 | #include "test_macros.h" |
20 | |
21 | #if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary) |
22 | # define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "") |
23 | # define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "") |
24 | #else |
25 | # define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "") |
26 | # define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "") |
27 | #endif |
28 | |
29 | template <class Tp> |
30 | struct ConvertsTo { |
31 | using RawTp = typename std::remove_cv< typename std::remove_reference<Tp>::type>::type; |
32 | |
33 | operator Tp() const { |
34 | return static_cast<Tp>(value); |
35 | } |
36 | |
37 | mutable RawTp value; |
38 | }; |
39 | |
40 | struct Base {}; |
41 | struct Derived : Base {}; |
42 | |
43 | |
44 | static_assert(std::is_same<decltype("abc" ), decltype(("abc" ))>::value, "" ); |
45 | ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype("abc" )); |
46 | ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype(("abc" ))); |
47 | ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, const char*&&); |
48 | |
49 | ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(int&, const ConvertsTo<int&>&); |
50 | ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(const int&, ConvertsTo<int&>&); |
51 | ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(Base&, Derived&); |
52 | |
53 | |
54 | static_assert(std::is_constructible<int&, std::reference_wrapper<int>>::value, "" ); |
55 | static_assert(std::is_constructible<int const&, std::reference_wrapper<int>>::value, "" ); |
56 | |
57 | template <class T> struct CannotDeduce { |
58 | using type = T; |
59 | }; |
60 | |
61 | template <class ...Args> |
62 | void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {} |
63 | |
64 | void compile_tests() { |
65 | { |
66 | F<int, int const&>(std::make_tuple(args: 42, args: 42)); |
67 | } |
68 | { |
69 | F<int, int const&>(std::make_tuple<const int&, const int&>(args: 42, args: 42)); |
70 | std::tuple<int, int const&> t(std::make_tuple<const int&, const int&>(args: 42, args: 42)); |
71 | } |
72 | { |
73 | auto fn = &F<int, std::string const&>; |
74 | fn(std::tuple<int, std::string const&>(42, std::string("a" ))); |
75 | fn(std::make_tuple(args: 42, args: std::string("a" ))); |
76 | } |
77 | { |
78 | Derived d; |
79 | std::tuple<Base&, Base const&> t(d, d); |
80 | } |
81 | { |
82 | ConvertsTo<int&> ct; |
83 | std::tuple<int, int&> t(42, ct); |
84 | } |
85 | } |
86 | |
87 | void allocator_tests() { |
88 | std::allocator<int> alloc; |
89 | int x = 42; |
90 | { |
91 | std::tuple<int&> t(std::ref(t&: x)); |
92 | assert(&std::get<0>(t) == &x); |
93 | std::tuple<int&> t1(std::allocator_arg, alloc, std::ref(t&: x)); |
94 | assert(&std::get<0>(t1) == &x); |
95 | } |
96 | { |
97 | auto r = std::ref(t&: x); |
98 | auto const& cr = r; |
99 | std::tuple<int&> t(r); |
100 | assert(&std::get<0>(t) == &x); |
101 | std::tuple<int&> t1(cr); |
102 | assert(&std::get<0>(t1) == &x); |
103 | std::tuple<int&> t2(std::allocator_arg, alloc, r); |
104 | assert(&std::get<0>(t2) == &x); |
105 | std::tuple<int&> t3(std::allocator_arg, alloc, cr); |
106 | assert(&std::get<0>(t3) == &x); |
107 | } |
108 | { |
109 | std::tuple<int const&> t(std::ref(t&: x)); |
110 | assert(&std::get<0>(t) == &x); |
111 | std::tuple<int const&> t2(std::cref(t: x)); |
112 | assert(&std::get<0>(t2) == &x); |
113 | std::tuple<int const&> t3(std::allocator_arg, alloc, std::ref(t&: x)); |
114 | assert(&std::get<0>(t3) == &x); |
115 | std::tuple<int const&> t4(std::allocator_arg, alloc, std::cref(t: x)); |
116 | assert(&std::get<0>(t4) == &x); |
117 | } |
118 | { |
119 | auto r = std::ref(t&: x); |
120 | auto cr = std::cref(t: x); |
121 | std::tuple<int const&> t(r); |
122 | assert(&std::get<0>(t) == &x); |
123 | std::tuple<int const&> t2(cr); |
124 | assert(&std::get<0>(t2) == &x); |
125 | std::tuple<int const&> t3(std::allocator_arg, alloc, r); |
126 | assert(&std::get<0>(t3) == &x); |
127 | std::tuple<int const&> t4(std::allocator_arg, alloc, cr); |
128 | assert(&std::get<0>(t4) == &x); |
129 | } |
130 | } |
131 | |
132 | |
133 | int main(int, char**) { |
134 | compile_tests(); |
135 | allocator_tests(); |
136 | |
137 | return 0; |
138 | } |
139 | |