1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
15 #include <type_traits>
18 #include "test_macros.h"
21 constexpr bool has_type
= requires
{
25 // A slightly simplified variation of std::tuple
29 template <class, class, class>
30 struct Tuple_helper
{};
31 template <class... Ts
, class... Us
>
32 struct 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
>...>;
36 template <class... Ts
, class... Us
, template <class> class TQual
, template <class> class UQual
>
37 struct std::basic_common_reference
< ::UserTuple
<Ts
...>, ::UserTuple
<Us
...>, TQual
, UQual
>
38 : ::Tuple_helper
<void, UserTuple
<TQual
<Ts
>...>, UserTuple
<UQual
<Us
>...> > {};
45 struct std::common_type
<X2
, Y2
> {
49 struct std::common_type
<Y2
, X2
> {
54 // -- If sizeof...(T) is zero, there shall be no member type.
55 static_assert(!has_type
<std::common_reference
<> >);
58 // -- Otherwise, if sizeof...(T) is one, let T0 denote the sole type in the
59 // pack T. The member typedef type shall denote the same type as T0.
60 static_assert(std::is_same_v
<std::common_reference_t
<void>, void>);
61 static_assert(std::is_same_v
<std::common_reference_t
<int>, int>);
62 static_assert(std::is_same_v
<std::common_reference_t
<int&>, int&>);
63 static_assert(std::is_same_v
<std::common_reference_t
<int&&>, int&&>);
64 static_assert(std::is_same_v
<std::common_reference_t
<int const>, int const>);
65 static_assert(std::is_same_v
<std::common_reference_t
<int const&>, int const&>);
66 static_assert(std::is_same_v
<std::common_reference_t
<int const&&>, int const&&>);
67 static_assert(std::is_same_v
<std::common_reference_t
<int volatile[]>, int volatile[]>);
68 static_assert(std::is_same_v
<std::common_reference_t
<int volatile (&)[]>, int volatile (&)[]>);
69 static_assert(std::is_same_v
<std::common_reference_t
<int volatile (&&)[]>, int volatile (&&)[]>);
70 static_assert(std::is_same_v
<std::common_reference_t
<void (&)()>, void (&)()>);
71 static_assert(std::is_same_v
<std::common_reference_t
<void (&&)()>, void (&&)()>);
74 // -- Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in
77 // -- If T1 and T2 are reference types and COMMON_REF(T1, T2) is well-formed,
78 // then the member typedef type denotes that type.
81 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
&>, B
&>);
82 static_assert(std::is_same_v
<std::common_reference_t
<B
const&, D
&>, B
const&>);
83 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
const&>, B
const&>);
84 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
const&, D
&>, B
const&>);
85 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
&, B
&, D
&>, B
&>);
87 static_assert(std::is_same_v
<std::common_reference_t
<B
&&, D
&&>, B
&&>);
88 static_assert(std::is_same_v
<std::common_reference_t
<B
const&&, D
&&>, B
const&&>);
89 static_assert(std::is_same_v
<std::common_reference_t
<B
&&, D
const&&>, B
const&&>);
90 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
&&>, B
const&>);
91 static_assert(std::is_same_v
<std::common_reference_t
<B
&, D
const&&>, B
const&>);
92 static_assert(std::is_same_v
<std::common_reference_t
<B
const&, D
&&>, B
const&>);
94 static_assert(std::is_same_v
<std::common_reference_t
<B
&&, D
&>, B
const&>);
95 static_assert(std::is_same_v
<std::common_reference_t
<B
&&, D
const&>, B
const&>);
96 static_assert(std::is_same_v
<std::common_reference_t
<B
const&&, D
&>, B
const&>);
98 static_assert(std::is_same_v
<std::common_reference_t
<int const&, int volatile&>, int const volatile&>);
99 static_assert(std::is_same_v
<std::common_reference_t
<int const volatile&&, int volatile&&>, int const volatile&&>);
101 static_assert(std::is_same_v
<std::common_reference_t
<int (&)[10], int (&&)[10]>, int const (&)[10]>);
102 static_assert(std::is_same_v
<std::common_reference_t
<int const (&)[10], int volatile (&)[10]>, int const volatile (&)[10]>);
105 // -- Otherwise, if basic_common_reference<remove_cvref_t<T1>,
106 // remove_cvref_t<T2>, XREF(T1), XREF(T2)>::type is well-formed, then the
107 // member typedef type denotes that type.
108 static_assert(std::is_same_v
<std::common_reference_t
<const UserTuple
<int, short>&, UserTuple
<int&, short volatile&>>,
109 UserTuple
<const int&, const volatile short&>>);
111 static_assert(std::is_same_v
<std::common_reference_t
<volatile UserTuple
<int, short>&, const UserTuple
<int, short>&>,
112 const volatile UserTuple
<int, short>&>);
115 // -- Otherwise, if COND_RES(T1, T2) is well-formed, then the member typedef
116 // type denotes that type.
117 static_assert(std::is_same_v
<std::common_reference_t
<void, void>, void>);
118 static_assert(std::is_same_v
<std::common_reference_t
<int, short>, int>);
119 static_assert(std::is_same_v
<std::common_reference_t
<int, short&>, int>);
120 static_assert(std::is_same_v
<std::common_reference_t
<int&, short&>, int>);
121 static_assert(std::is_same_v
<std::common_reference_t
<int&, short>, int>);
123 // tricky volatile reference case
124 static_assert(std::is_same_v
<std::common_reference_t
<int&&, int volatile&>, int>);
125 static_assert(std::is_same_v
<std::common_reference_t
<int volatile&, int&&>, int>);
127 static_assert(std::is_same_v
<std::common_reference_t
<int (&)[10], int (&)[11]>, int*>);
129 // https://github.com/ericniebler/stl2/issues/338
133 static_assert(std::is_same_v
<std::common_reference_t
<int&, MyIntRef
>, MyIntRef
>);
136 // -- Otherwise, if common_type_t<T1, T2> is well-formed, then the member
137 // typedef type denotes that type.
139 moveonly() = default;
140 moveonly(moveonly
&&) = default;
141 moveonly
& operator=(moveonly
&&) = default;
143 struct moveonly2
: moveonly
{};
145 static_assert(std::is_same_v
<std::common_reference_t
<moveonly
const&, moveonly
>, moveonly
>);
146 static_assert(std::is_same_v
<std::common_reference_t
<moveonly2
const&, moveonly
>, moveonly
>);
147 static_assert(std::is_same_v
<std::common_reference_t
<moveonly
const&, moveonly2
>, moveonly
>);
149 static_assert(std::is_same_v
<std::common_reference_t
<X2
&, Y2
const&>, Z2
>);
152 // -- Otherwise, there shall be no member type.
153 static_assert(!has_type
<std::common_reference
<volatile UserTuple
<short>&, const UserTuple
<int, short>&> >);
156 // -- Otherwise, if sizeof...(T) is greater than two, let T1, T2, and Rest,
157 // respectively, denote the first, second, and (pack of) remaining types
158 // comprising T. Let C be the type common_reference_t<T1, T2>. Then:
160 // -- If there is such a type C, the member typedef type shall denote the
161 // same type, if any, as common_reference_t<C, Rest...>.
162 static_assert(std::is_same_v
<std::common_reference_t
<int, int, int>, int>);
163 static_assert(std::is_same_v
<std::common_reference_t
<int&&, int const&, int volatile&>, int const volatile&>);
164 static_assert(std::is_same_v
<std::common_reference_t
<int&&, int const&, float&>, float>);
167 // -- Otherwise, there shall be no member type.
168 static_assert(!has_type
<std::common_reference
<int, short, int, char*> >);
170 #if TEST_STD_VER > 20
171 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int, int>>, std::tuple
<int, int>>);
172 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int, long>, std::tuple
<long, int>>, std::tuple
<long, long>>);
173 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int&, const int&>, std::tuple
<const int&, int>>,
174 std::tuple
<const int&, int>>);
175 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int&, volatile int&>, std::tuple
<volatile int&, int>>,
176 std::tuple
<volatile int&, int>>);
177 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int&, const volatile int&>, std::tuple
<const volatile int&, int>>,
178 std::tuple
<const volatile int&, int>>);
179 static_assert(!has_type
<std::common_reference_t
<std::tuple
<const int&, volatile int&>, std::tuple
<volatile int&, const int&>>>);
181 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int, X2
>, std::tuple
<int, Y2
>>, std::tuple
<int, Z2
>>);
182 static_assert(std::is_same_v
<std::common_reference_t
<std::tuple
<int, X2
>, std::tuple
<int, Y2
>>, std::tuple
<int, Z2
>>);
183 static_assert(!has_type
<std::common_reference
<std::tuple
<int, const X2
>, std::tuple
<float, const Z2
>>>);
184 static_assert(!has_type
<std::common_reference
<std::tuple
<int, X2
>, std::tuple
<float, Z2
>>>);
185 static_assert(!has_type
<std::common_reference
<std::tuple
<int, X2
>, int, X2
>>);
188 template <template<class> class TQual
, template<class> class UQual
>
189 struct std::basic_common_reference
<A
, std::tuple
<B
>, TQual
, UQual
> {
190 using type
= tuple
<UQual
<B
>>;
193 static_assert(std::is_same_v
<std::common_reference_t
<A
, std::tuple
<B
>, std::tuple
<D
>>, std::tuple
<B
>>);
196 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int, int>>,
197 std::pair
<int, int>>);
198 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int, long>, std::pair
<long, int>>,
199 std::pair
<long, long>>);
200 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int&, const int&>, std::pair
<const int&, int>>,
201 std::pair
<const int&, int>>);
202 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int&, volatile int&>, std::pair
<volatile int&, int>>,
203 std::pair
<volatile int&, int>>);
204 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int&, const volatile int&>, std::pair
<const volatile int&, int>>,
205 std::pair
<const volatile int&, int>>);
206 static_assert(!has_type
<std::common_reference_t
<std::pair
<const int&, volatile int&>,
207 std::pair
<volatile int&, const int&>>>);
209 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int, X2
>, std::pair
<int, Y2
>>, std::pair
<int, Z2
>>);
210 static_assert(std::is_same_v
<std::common_reference_t
<std::pair
<int, X2
>, std::pair
<int, Y2
>>, std::pair
<int, Z2
>>);
211 static_assert(!has_type
<std::common_reference
<std::pair
<int, const X2
>, std::pair
<float, const Z2
>>>);
212 static_assert(!has_type
<std::common_reference
<std::pair
<int, X2
>, std::pair
<float, Z2
>>>);
213 static_assert(!has_type
<std::common_reference
<std::pair
<int, X2
>, int, X2
>>);