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

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp