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, c++17
10
11// type_traits
12// common_reference
13
14#include <tuple>
15#include <type_traits>
16#include <utility>
17
18#include "test_macros.h"
19
20template <class T>
21constexpr bool has_type = requires {
22 typename T::type;
23};
24
25// A slightly simplified variation of std::tuple
26template <class...>
27struct UserTuple {};
28
29template <class, class, class>
30struct Tuple_helper {};
31template <class... Ts, class... Us>
32struct Tuple_helper<std::void_t<std::common_reference_t<Ts, Us>...>, UserTuple<Ts...>, UserTuple<Us...> > {
33 using type = UserTuple<std::common_reference_t<Ts, Us>...>;
34};
35
36namespace std {
37template <class... Ts, class... Us, template <class> class TQual, template <class> class UQual>
38struct basic_common_reference< ::UserTuple<Ts...>, ::UserTuple<Us...>, TQual, UQual>
39 : ::Tuple_helper<void, UserTuple<TQual<Ts>...>, UserTuple<UQual<Us>...> > {};
40} // namespace std
41
42struct X2 {};
43struct Y2 {};
44struct Z2 {};
45
46namespace std {
47template <>
48struct common_type<X2, Y2> {
49 using type = Z2;
50};
51template <>
52struct common_type<Y2, X2> {
53 using type = Z2;
54};
55} // namespace std
56
57// (6.1)
58// -- If sizeof...(T) is zero, there shall be no member type.
59static_assert(!has_type<std::common_reference<> >);
60
61// (6.2)
62// -- Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the
63// pack T. The member typedef type shall denote the same type as T0.
64static_assert(std::is_same_v<std::common_reference_t<void>, void>);
65static_assert(std::is_same_v<std::common_reference_t<int>, int>);
66static_assert(std::is_same_v<std::common_reference_t<int&>, int&>);
67static_assert(std::is_same_v<std::common_reference_t<int&&>, int&&>);
68static_assert(std::is_same_v<std::common_reference_t<int const>, int const>);
69static_assert(std::is_same_v<std::common_reference_t<int const&>, int const&>);
70static_assert(std::is_same_v<std::common_reference_t<int const&&>, int const&&>);
71static_assert(std::is_same_v<std::common_reference_t<int volatile[]>, int volatile[]>);
72static_assert(std::is_same_v<std::common_reference_t<int volatile (&)[]>, int volatile (&)[]>);
73static_assert(std::is_same_v<std::common_reference_t<int volatile (&&)[]>, int volatile (&&)[]>);
74static_assert(std::is_same_v<std::common_reference_t<void (&)()>, void (&)()>);
75static_assert(std::is_same_v<std::common_reference_t<void (&&)()>, void (&&)()>);
76
77// (6.3)
78// -- Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in
79// the pack T. Then
80// (6.3.1)
81// -- If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed,
82// then the member typedef type denotes that type.
83struct B {};
84struct D : B {};
85static_assert(std::is_same_v<std::common_reference_t<B&, D&>, B&>);
86static_assert(std::is_same_v<std::common_reference_t<B const&, D&>, B const&>);
87static_assert(std::is_same_v<std::common_reference_t<B&, D const&>, B const&>);
88static_assert(std::is_same_v<std::common_reference_t<B&, D const&, D&>, B const&>);
89static_assert(std::is_same_v<std::common_reference_t<B&, D&, B&, D&>, B&>);
90
91static_assert(std::is_same_v<std::common_reference_t<B&&, D&&>, B&&>);
92static_assert(std::is_same_v<std::common_reference_t<B const&&, D&&>, B const&&>);
93static_assert(std::is_same_v<std::common_reference_t<B&&, D const&&>, B const&&>);
94static_assert(std::is_same_v<std::common_reference_t<B&, D&&>, B const&>);
95static_assert(std::is_same_v<std::common_reference_t<B&, D const&&>, B const&>);
96static_assert(std::is_same_v<std::common_reference_t<B const&, D&&>, B const&>);
97
98static_assert(std::is_same_v<std::common_reference_t<B&&, D&>, B const&>);
99static_assert(std::is_same_v<std::common_reference_t<B&&, D const&>, B const&>);
100static_assert(std::is_same_v<std::common_reference_t<B const&&, D&>, B const&>);
101
102static_assert(std::is_same_v<std::common_reference_t<int const&, int volatile&>, int const volatile&>);
103static_assert(std::is_same_v<std::common_reference_t<int const volatile&&, int volatile&&>, int const volatile&&>);
104
105static_assert(std::is_same_v<std::common_reference_t<int (&)[10], int (&&)[10]>, int const (&)[10]>);
106static_assert(std::is_same_v<std::common_reference_t<int const (&)[10], int volatile (&)[10]>, int const volatile (&)[10]>);
107
108// (6.3.2)
109// -- Otherwise, if basic_common_reference<remove_cvref_t<T1>,
110// remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type is well-formed, then the
111// member typedef type denotes that type.
112static_assert(std::is_same_v<std::common_reference_t<const UserTuple<int, short>&, UserTuple<int&, short volatile&>>,
113 UserTuple<const int&, const volatile short&>>);
114
115static_assert(std::is_same_v<std::common_reference_t<volatile UserTuple<int, short>&, const UserTuple<int, short>&>,
116 const volatile UserTuple<int, short>&>);
117
118// (6.3.3)
119// -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef
120// type denotes that type.
121static_assert(std::is_same_v<std::common_reference_t<void, void>, void>);
122static_assert(std::is_same_v<std::common_reference_t<int, short>, int>);
123static_assert(std::is_same_v<std::common_reference_t<int, short&>, int>);
124static_assert(std::is_same_v<std::common_reference_t<int&, short&>, int>);
125static_assert(std::is_same_v<std::common_reference_t<int&, short>, int>);
126
127// tricky volatile reference case
128static_assert(std::is_same_v<std::common_reference_t<int&&, int volatile&>, int>);
129static_assert(std::is_same_v<std::common_reference_t<int volatile&, int&&>, int>);
130
131static_assert(std::is_same_v<std::common_reference_t<int (&)[10], int (&)[11]>, int*>);
132
133// https://github.com/ericniebler/stl2/issues/338
134struct MyIntRef {
135 MyIntRef(int&);
136};
137static_assert(std::is_same_v<std::common_reference_t<int&, MyIntRef>, MyIntRef>);
138
139// (6.3.4)
140// -- Otherwise, if common_type_t<T1, T2> is well-formed, then the member
141// typedef type denotes that type.
142struct moveonly {
143 moveonly() = default;
144 moveonly(moveonly&&) = default;
145 moveonly& operator=(moveonly&&) = default;
146};
147struct moveonly2 : moveonly {};
148
149static_assert(std::is_same_v<std::common_reference_t<moveonly const&, moveonly>, moveonly>);
150static_assert(std::is_same_v<std::common_reference_t<moveonly2 const&, moveonly>, moveonly>);
151static_assert(std::is_same_v<std::common_reference_t<moveonly const&, moveonly2>, moveonly>);
152
153static_assert(std::is_same_v<std::common_reference_t<X2&, Y2 const&>, Z2>);
154
155// (6.3.5)
156// -- Otherwise, there shall be no member type.
157static_assert(!has_type<std::common_reference<volatile UserTuple<short>&, const UserTuple<int, short>&> >);
158
159// (6.4)
160// -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest,
161// respectively, denote the first, second, and (pack of) remaining types
162// comprising T. Let C be the type common_reference_t<T1, T2>. Then:
163// (6.4.1)
164// -- If there is such a type C, the member typedef type shall denote the
165// same type, if any, as common_reference_t<C, Rest...>.
166static_assert(std::is_same_v<std::common_reference_t<int, int, int>, int>);
167static_assert(std::is_same_v<std::common_reference_t<int&&, int const&, int volatile&>, int const volatile&>);
168static_assert(std::is_same_v<std::common_reference_t<int&&, int const&, float&>, float>);
169
170// (6.4.2)
171// -- Otherwise, there shall be no member type.
172static_assert(!has_type<std::common_reference<int, short, int, char*> >);
173
174#if TEST_STD_VER > 20
175static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, int>>, std::tuple<int, int>>);
176static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, long>, std::tuple<long, int>>, std::tuple<long, long>>);
177static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, const int&>, std::tuple<const int&, int>>,
178 std::tuple<const int&, int>>);
179static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, volatile int&>, std::tuple<volatile int&, int>>,
180 std::tuple<volatile int&, int>>);
181static_assert(std::is_same_v<std::common_reference_t<std::tuple<int&, const volatile int&>, std::tuple<const volatile int&, int>>,
182 std::tuple<const volatile int&, int>>);
183static_assert(!has_type<std::common_reference_t<std::tuple<const int&, volatile int&>, std::tuple<volatile int&, const int&>>>);
184
185static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);
186static_assert(std::is_same_v<std::common_reference_t<std::tuple<int, X2>, std::tuple<int, Y2>>, std::tuple<int, Z2>>);
187static_assert(!has_type<std::common_reference<std::tuple<int, const X2>, std::tuple<float, const Z2>>>);
188static_assert(!has_type<std::common_reference<std::tuple<int, X2>, std::tuple<float, Z2>>>);
189static_assert(!has_type<std::common_reference<std::tuple<int, X2>, int, X2>>);
190
191struct A {};
192template <template<class> class TQual, template<class> class UQual>
193struct std::basic_common_reference<A, std::tuple<B>, TQual, UQual> {
194 using type = tuple<UQual<B>>;
195};
196
197static_assert(std::is_same_v<std::common_reference_t<A, std::tuple<B>, std::tuple<D>>, std::tuple<B>>);
198
199
200static_assert(std::is_same_v<std::common_reference_t<std::pair<int, int>>,
201 std::pair<int, int>>);
202static_assert(std::is_same_v<std::common_reference_t<std::pair<int, long>, std::pair<long, int>>,
203 std::pair<long, long>>);
204static_assert(std::is_same_v<std::common_reference_t<std::pair<int&, const int&>, std::pair<const int&, int>>,
205 std::pair<const int&, int>>);
206static_assert(std::is_same_v<std::common_reference_t<std::pair<int&, volatile int&>, std::pair<volatile int&, int>>,
207 std::pair<volatile int&, int>>);
208static_assert(std::is_same_v<std::common_reference_t<std::pair<int&, const volatile int&>, std::pair<const volatile int&, int>>,
209 std::pair<const volatile int&, int>>);
210static_assert(!has_type<std::common_reference_t<std::pair<const int&, volatile int&>,
211 std::pair<volatile int&, const int&>>>);
212
213static_assert(std::is_same_v<std::common_reference_t<std::pair<int, X2>, std::pair<int, Y2>>, std::pair<int, Z2>>);
214static_assert(std::is_same_v<std::common_reference_t<std::pair<int, X2>, std::pair<int, Y2>>, std::pair<int, Z2>>);
215static_assert(!has_type<std::common_reference<std::pair<int, const X2>, std::pair<float, const Z2>>>);
216static_assert(!has_type<std::common_reference<std::pair<int, X2>, std::pair<float, Z2>>>);
217static_assert(!has_type<std::common_reference<std::pair<int, X2>, int, X2>>);
218#endif
219

source code of libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp