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 20 template <class T> 21 constexpr bool has_type = requires { 22 typename T::type; 23 }; 24 25 // A slightly simplified variation of std::tuple 26 template <class...> 27 struct UserTuple {}; 28 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>...>; 34 }; 35 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>...> > {}; 39 40 struct X2 {}; 41 struct Y2 {}; 42 struct Z2 {}; 43 44 template <> 45 struct std::common_type<X2, Y2> { 46 using type = Z2; 47 }; 48 template <> 49 struct std::common_type<Y2, X2> { 50 using type = Z2; 51 }; 52 53 // (6.1) 54 // -- If sizeof...(T) is zero, there shall be no member type. 55 static_assert(!has_type<std::common_reference<> >); 56 57 // (6.2) 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 (&&)()>); 72 73 // (6.3) 74 // -- Otherwise, if sizeof...(T) is two, let T1 and T2 denote the two types in 75 // the pack T. Then 76 // (6.3.1) 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. 79 struct B {}; 80 struct D : B {}; 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&>); 86 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&>); 93 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&>); 97 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&&>); 100 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]>); 103 104 // (6.3.2) 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&>>); 110 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>&>); 113 114 // (6.3.3) 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>); 122 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>); 126 127 static_assert(std::is_same_v<std::common_reference_t<int (&)[10], int (&)[11]>, int*>); 128 129 // https://github.com/ericniebler/stl2/issues/338 130 struct MyIntRef { 131 MyIntRef(int&); 132 }; 133 static_assert(std::is_same_v<std::common_reference_t<int&, MyIntRef>, MyIntRef>); 134 135 // (6.3.4) 136 // -- Otherwise, if common_type_t<T1, T2> is well-formed, then the member 137 // typedef type denotes that type. 138 struct moveonly { 139 moveonly() = default; 140 moveonly(moveonly&&) = default; 141 moveonly& operator=(moveonly&&) = default; 142 }; 143 struct moveonly2 : moveonly {}; 144 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>); 148 149 static_assert(std::is_same_v<std::common_reference_t<X2&, Y2 const&>, Z2>); 150 151 // (6.3.5) 152 // -- Otherwise, there shall be no member type. 153 static_assert(!has_type<std::common_reference<volatile UserTuple<short>&, const UserTuple<int, short>&> >); 154 155 // (6.4) 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: 159 // (6.4.1) 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>); 165 166 // (6.4.2) 167 // -- Otherwise, there shall be no member type. 168 static_assert(!has_type<std::common_reference<int, short, int, char*> >); 169 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&>>>); 180 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>>); 186 187 struct A {}; 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>>; 191 }; 192 193 static_assert(std::is_same_v<std::common_reference_t<A, std::tuple<B>, std::tuple<D>>, std::tuple<B>>); 194 195 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&>>>); 208 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>>); 214 #endif 215