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 // template<class T, class U> 12 // concept same_as; 13 14 #include <concepts> 15 #include <type_traits> 16 17 struct S1 {}; 18 struct S2 { 19 int i; 20 21 int& f(); 22 double g(int x) const; 23 }; 24 struct S3 { 25 int& r; 26 }; 27 struct S4 { 28 int&& r; 29 }; 30 struct S5 { 31 int* p; 32 }; 33 34 class C1 {}; 35 class C2 { 36 [[maybe_unused]] int i; 37 }; 38 39 class C3 { 40 public: 41 int i; 42 }; 43 44 template <class T1, class T2 = T1> 45 class C4 { 46 int t1; 47 int t2; 48 }; 49 50 template <class T1, class T2 = T1> 51 class C5 { 52 [[maybe_unused]] T1 t1; 53 54 public: 55 T2 t2; 56 }; 57 58 template <class T1, class T2 = T1> 59 class C6 { 60 public: 61 [[maybe_unused]] T1 t1; 62 [[maybe_unused]] T2 t2; 63 }; 64 65 template <class T> 66 struct identity { 67 using type = T; 68 }; 69 70 template <template <typename> class Modifier = identity> 71 void CheckSameAs() { 72 static_assert( 73 std::same_as<typename Modifier<int>::type, typename Modifier<int>::type>); 74 static_assert( 75 std::same_as<typename Modifier<S1>::type, typename Modifier<S1>::type>); 76 static_assert( 77 std::same_as<typename Modifier<S2>::type, typename Modifier<S2>::type>); 78 static_assert( 79 std::same_as<typename Modifier<S3>::type, typename Modifier<S3>::type>); 80 static_assert( 81 std::same_as<typename Modifier<S4>::type, typename Modifier<S4>::type>); 82 static_assert( 83 std::same_as<typename Modifier<S5>::type, typename Modifier<S5>::type>); 84 static_assert( 85 std::same_as<typename Modifier<C1>::type, typename Modifier<C1>::type>); 86 static_assert( 87 std::same_as<typename Modifier<C2>::type, typename Modifier<C2>::type>); 88 static_assert( 89 std::same_as<typename Modifier<C3>::type, typename Modifier<C3>::type>); 90 static_assert(std::same_as<typename Modifier<C4<int> >::type, 91 typename Modifier<C4<int> >::type>); 92 static_assert(std::same_as<typename Modifier<C4<int&> >::type, 93 typename Modifier<C4<int&> >::type>); 94 static_assert(std::same_as<typename Modifier<C4<int&&> >::type, 95 typename Modifier<C4<int&&> >::type>); 96 static_assert(std::same_as<typename Modifier<C5<int> >::type, 97 typename Modifier<C5<int> >::type>); 98 static_assert(std::same_as<typename Modifier<C5<int&> >::type, 99 typename Modifier<C5<int&> >::type>); 100 static_assert(std::same_as<typename Modifier<C5<int&&> >::type, 101 typename Modifier<C5<int&&> >::type>); 102 static_assert(std::same_as<typename Modifier<C6<int> >::type, 103 typename Modifier<C6<int> >::type>); 104 static_assert(std::same_as<typename Modifier<C6<int&> >::type, 105 typename Modifier<C6<int&> >::type>); 106 static_assert(std::same_as<typename Modifier<C6<int&&> >::type, 107 typename Modifier<C6<int&&> >::type>); 108 109 static_assert(std::same_as<typename Modifier<void>::type, 110 typename Modifier<void>::type>); 111 } 112 113 template <template <typename> class Modifier1, 114 template <typename> class Modifier2> 115 void CheckNotSameAs() { 116 static_assert(!std::same_as<typename Modifier1<int>::type, 117 typename Modifier2<int>::type>); 118 static_assert(!std::same_as<typename Modifier1<S1>::type, 119 typename Modifier2<S1>::type>); 120 static_assert(!std::same_as<typename Modifier1<S2>::type, 121 typename Modifier2<S2>::type>); 122 static_assert(!std::same_as<typename Modifier1<S3>::type, 123 typename Modifier2<S3>::type>); 124 static_assert(!std::same_as<typename Modifier1<S4>::type, 125 typename Modifier2<S4>::type>); 126 static_assert(!std::same_as<typename Modifier1<S5>::type, 127 typename Modifier2<S5>::type>); 128 static_assert(!std::same_as<typename Modifier1<C1>::type, 129 typename Modifier2<C1>::type>); 130 static_assert(!std::same_as<typename Modifier1<C2>::type, 131 typename Modifier2<C2>::type>); 132 static_assert(!std::same_as<typename Modifier1<C3>::type, 133 typename Modifier2<C3>::type>); 134 static_assert(!std::same_as<typename Modifier1<C4<int> >::type, 135 typename Modifier2<C4<int> >::type>); 136 static_assert(!std::same_as<typename Modifier1<C4<int&> >::type, 137 typename Modifier2<C4<int&> >::type>); 138 static_assert(!std::same_as<typename Modifier1<C4<int&&> >::type, 139 typename Modifier2<C4<int&&> >::type>); 140 static_assert(!std::same_as<typename Modifier1<C5<int> >::type, 141 typename Modifier2<C5<int> >::type>); 142 static_assert(!std::same_as<typename Modifier1<C5<int&> >::type, 143 typename Modifier2<C5<int&> >::type>); 144 static_assert(!std::same_as<typename Modifier1<C5<int&&> >::type, 145 typename Modifier2<C5<int&&> >::type>); 146 static_assert(!std::same_as<typename Modifier1<C6<int> >::type, 147 typename Modifier2<C6<int> >::type>); 148 static_assert(!std::same_as<typename Modifier1<C6<int&> >::type, 149 typename Modifier2<C6<int&> >::type>); 150 static_assert(!std::same_as<typename Modifier1<C6<int&&> >::type, 151 typename Modifier2<C6<int&&> >::type>); 152 } 153 154 // Checks subsumption works as intended 155 template <class T, class U> 156 requires std::same_as<T, U> void SubsumptionTest(); 157 158 // clang-format off 159 template <class T, class U> 160 requires std::same_as<U, T> && true // NOLINT(readability-simplify-boolean-expr) 161 int SubsumptionTest(); 162 // clang-format on 163 164 static_assert(std::same_as<int, decltype(SubsumptionTest<int, int>())>); 165 static_assert(std::same_as<int, decltype(SubsumptionTest<void, void>())>); 166 static_assert( 167 std::same_as<int, decltype(SubsumptionTest<int (*)(), int (*)()>())>); 168 static_assert( 169 std::same_as< 170 int, decltype(SubsumptionTest<double (&)(int), double (&)(int)>())>); 171 static_assert( 172 std::same_as<int, decltype(SubsumptionTest<int S2::*, int S2::*>())>); 173 static_assert( 174 std::same_as<int, 175 decltype(SubsumptionTest<int& (S2::*)(), int& (S2::*)()>())>); 176 177 int main(int, char**) { 178 { // Checks std::same_as<T, T> is true 179 CheckSameAs(); 180 181 // Checks std::same_as<T&, T&> is true 182 CheckSameAs<std::add_lvalue_reference>(); 183 184 // Checks std::same_as<T&&, T&&> is true 185 CheckSameAs<std::add_rvalue_reference>(); 186 187 // Checks std::same_as<const T, const T> is true 188 CheckSameAs<std::add_const>(); 189 190 // Checks std::same_as<volatile T, volatile T> is true 191 CheckSameAs<std::add_volatile>(); 192 193 // Checks std::same_as<const volatile T, const volatile T> is true 194 CheckSameAs<std::add_cv>(); 195 196 // Checks std::same_as<T*, T*> is true 197 CheckSameAs<std::add_pointer>(); 198 199 // Checks concrete types are identical 200 static_assert(std::same_as<void, void>); 201 202 using Void = void; 203 static_assert(std::same_as<void, Void>); 204 205 static_assert(std::same_as<int[1], int[1]>); 206 static_assert(std::same_as<int[2], int[2]>); 207 208 static_assert(std::same_as<int (*)(), int (*)()>); 209 static_assert(std::same_as<void (&)(), void (&)()>); 210 static_assert(std::same_as<S1& (*)(S1), S1& (*)(S1)>); 211 static_assert(std::same_as<C1& (&)(S1, int), C1& (&)(S1, int)>); 212 213 static_assert(std::same_as<int S2::*, int S2::*>); 214 static_assert(std::same_as<double S2::*, double S2::*>); 215 216 static_assert(std::same_as<int& (S2::*)(), int& (S2::*)()>); 217 static_assert(std::same_as<double& (S2::*)(int), double& (S2::*)(int)>); 218 } 219 220 { // Checks that `T` and `T&` are distinct types 221 CheckNotSameAs<identity, std::add_lvalue_reference>(); 222 CheckNotSameAs<std::add_lvalue_reference, identity>(); 223 224 // Checks that `T` and `T&&` are distinct types 225 CheckNotSameAs<identity, std::add_rvalue_reference>(); 226 CheckNotSameAs<std::add_rvalue_reference, identity>(); 227 228 // Checks that `T` and `const T` are distinct types 229 CheckNotSameAs<identity, std::add_const>(); 230 CheckNotSameAs<std::add_const, identity>(); 231 232 // Checks that `T` and `volatile T` are distinct types 233 CheckNotSameAs<identity, std::add_volatile>(); 234 CheckNotSameAs<std::add_volatile, identity>(); 235 236 // Checks that `T` and `const volatile T` are distinct types 237 CheckNotSameAs<identity, std::add_cv>(); 238 CheckNotSameAs<std::add_cv, identity>(); 239 240 // Checks that `const T` and `volatile T` are distinct types 241 CheckNotSameAs<std::add_const, std::add_volatile>(); 242 CheckNotSameAs<std::add_volatile, std::add_const>(); 243 244 // Checks that `const T` and `const volatile T` are distinct types 245 CheckNotSameAs<std::add_const, std::add_cv>(); 246 CheckNotSameAs<std::add_cv, std::add_const>(); 247 248 // Checks that `volatile T` and `const volatile T` are distinct types 249 CheckNotSameAs<std::add_volatile, std::add_cv>(); 250 CheckNotSameAs<std::add_cv, std::add_volatile>(); 251 252 // Checks `T&` and `T&&` are distinct types 253 CheckNotSameAs<std::add_lvalue_reference, std::add_rvalue_reference>(); 254 CheckNotSameAs<std::add_rvalue_reference, std::add_lvalue_reference>(); 255 } 256 257 { // Checks different type names are distinct types 258 static_assert(!std::same_as<S1, C1>); 259 static_assert(!std::same_as<C4<int>, C5<int> >); 260 static_assert(!std::same_as<C4<int>, C5<int> >); 261 static_assert(!std::same_as<C5<int, double>, C5<double, int> >); 262 263 static_assert(!std::same_as<int&, const int&>); 264 static_assert(!std::same_as<int&, volatile int&>); 265 static_assert(!std::same_as<int&, const volatile int&>); 266 267 static_assert(!std::same_as<int&&, const int&>); 268 static_assert(!std::same_as<int&&, volatile int&>); 269 static_assert(!std::same_as<int&&, const volatile int&>); 270 271 static_assert(!std::same_as<int&, const int&&>); 272 static_assert(!std::same_as<int&, volatile int&&>); 273 static_assert(!std::same_as<int&, const volatile int&&>); 274 275 static_assert(!std::same_as<int&&, const int&&>); 276 static_assert(!std::same_as<int&&, volatile int&&>); 277 static_assert(!std::same_as<int&&, const volatile int&&>); 278 279 static_assert(!std::same_as<void, int>); 280 281 static_assert(!std::same_as<int[1], int[2]>); 282 static_assert(!std::same_as<double[1], int[2]>); 283 284 static_assert(!std::same_as<int* (*)(), const int* (*)()>); 285 static_assert(!std::same_as<void (&)(), void (&)(S1)>); 286 static_assert(!std::same_as<S1 (*)(S1), S1& (*)(S1)>); 287 static_assert(!std::same_as<C3 (&)(int), C1& (&)(S1, int)>); 288 289 static_assert(!std::same_as<int S2::*, double S2::*>); 290 291 static_assert(!std::same_as<int& (S2::*)(), double& (S2::*)(int)>); 292 } 293 294 return 0; 295 } 296