296 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<class T, class U>12// concept same_as;13 14#include <concepts>15#include <type_traits>16 17struct S1 {};18struct S2 {19 int i;20 21 int& f();22 double g(int x) const;23};24struct S3 {25 int& r;26};27struct S4 {28 int&& r;29};30struct S5 {31 int* p;32};33 34class C1 {};35class C2 {36 [[maybe_unused]] int i;37};38 39class C3 {40public:41 int i;42};43 44template <class T1, class T2 = T1>45class C4 {46 int t1;47 int t2;48};49 50template <class T1, class T2 = T1>51class C5 {52 [[maybe_unused]] T1 t1;53 54public:55 T2 t2;56};57 58template <class T1, class T2 = T1>59class C6 {60public:61 [[maybe_unused]] T1 t1;62 [[maybe_unused]] T2 t2;63};64 65template <class T>66struct identity {67 using type = T;68};69 70template <template <typename> class Modifier = identity>71void 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 113template <template <typename> class Modifier1,114 template <typename> class Modifier2>115void 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 intended155template <class T, class U>156requires std::same_as<T, U> void SubsumptionTest();157 158// clang-format off159template <class T, class U>160requires std::same_as<U, T> && true // NOLINT(readability-simplify-boolean-expr)161int SubsumptionTest();162// clang-format on163 164static_assert(std::same_as<int, decltype(SubsumptionTest<int, int>())>);165static_assert(std::same_as<int, decltype(SubsumptionTest<void, void>())>);166static_assert(167 std::same_as<int, decltype(SubsumptionTest<int (*)(), int (*)()>())>);168static_assert(169 std::same_as<170 int, decltype(SubsumptionTest<double (&)(int), double (&)(int)>())>);171static_assert(172 std::same_as<int, decltype(SubsumptionTest<int S2::*, int S2::*>())>);173static_assert(174 std::same_as<int,175 decltype(SubsumptionTest<int& (S2::*)(), int& (S2::*)()>())>);176 177int main(int, char**) {178 { // Checks std::same_as<T, T> is true179 CheckSameAs();180 181 // Checks std::same_as<T&, T&> is true182 CheckSameAs<std::add_lvalue_reference>();183 184 // Checks std::same_as<T&&, T&&> is true185 CheckSameAs<std::add_rvalue_reference>();186 187 // Checks std::same_as<const T, const T> is true188 CheckSameAs<std::add_const>();189 190 // Checks std::same_as<volatile T, volatile T> is true191 CheckSameAs<std::add_volatile>();192 193 // Checks std::same_as<const volatile T, const volatile T> is true194 CheckSameAs<std::add_cv>();195 196 // Checks std::same_as<T*, T*> is true197 CheckSameAs<std::add_pointer>();198 199 // Checks concrete types are identical200 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 types221 CheckNotSameAs<identity, std::add_lvalue_reference>();222 CheckNotSameAs<std::add_lvalue_reference, identity>();223 224 // Checks that `T` and `T&&` are distinct types225 CheckNotSameAs<identity, std::add_rvalue_reference>();226 CheckNotSameAs<std::add_rvalue_reference, identity>();227 228 // Checks that `T` and `const T` are distinct types229 CheckNotSameAs<identity, std::add_const>();230 CheckNotSameAs<std::add_const, identity>();231 232 // Checks that `T` and `volatile T` are distinct types233 CheckNotSameAs<identity, std::add_volatile>();234 CheckNotSameAs<std::add_volatile, identity>();235 236 // Checks that `T` and `const volatile T` are distinct types237 CheckNotSameAs<identity, std::add_cv>();238 CheckNotSameAs<std::add_cv, identity>();239 240 // Checks that `const T` and `volatile T` are distinct types241 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 types245 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 types249 CheckNotSameAs<std::add_volatile, std::add_cv>();250 CheckNotSameAs<std::add_cv, std::add_volatile>();251 252 // Checks `T&` and `T&&` are distinct types253 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 types258 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