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
29template <class Tp>
30struct 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
40struct Base {};
41struct Derived : Base {};
42
43
44static_assert(std::is_same<decltype("abc"), decltype(("abc"))>::value, "");
45ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype("abc"));
46ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, decltype(("abc")));
47ASSERT_REFERENCE_BINDS_TEMPORARY(std::string const&, const char*&&);
48
49ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(int&, const ConvertsTo<int&>&);
50ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(const int&, ConvertsTo<int&>&);
51ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(Base&, Derived&);
52
53
54static_assert(std::is_constructible<int&, std::reference_wrapper<int>>::value, "");
55static_assert(std::is_constructible<int const&, std::reference_wrapper<int>>::value, "");
56
57template <class T> struct CannotDeduce {
58 using type = T;
59};
60
61template <class ...Args>
62void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {}
63
64void 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
87void 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
133int main(int, char**) {
134 compile_tests();
135 allocator_tests();
136
137 return 0;
138}
139

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