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