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 Cat = partial_ordering> 13 // concept three_way_comparable = // see below 14 15 #include <compare> 16 17 #include "compare_types.h" 18 #include "test_macros.h" 19 20 namespace fundamentals { 21 // with default ordering 22 static_assert(std::three_way_comparable<int>); 23 static_assert(std::three_way_comparable<double>); 24 static_assert(std::three_way_comparable<void*>); 25 static_assert(std::three_way_comparable<char*>); 26 static_assert(std::three_way_comparable<char const*>); 27 static_assert(std::three_way_comparable<char volatile*>); 28 static_assert(std::three_way_comparable<char const volatile*>); 29 static_assert(std::three_way_comparable<wchar_t&>); 30 #ifndef TEST_HAS_NO_CHAR8_T 31 static_assert(std::three_way_comparable<char8_t const&>); 32 #endif 33 #ifndef TEST_HAS_NO_UNICODE_CHARS 34 static_assert(std::three_way_comparable<char16_t volatile&>); 35 static_assert(std::three_way_comparable<char32_t const volatile&>); 36 #endif 37 #ifndef TEST_HAS_NO_INT128 38 static_assert(std::three_way_comparable<__int128_t const&>); 39 static_assert(std::three_way_comparable<__uint128_t const&>); 40 #endif 41 static_assert(std::three_way_comparable<unsigned char&&>); 42 static_assert(std::three_way_comparable<unsigned short const&&>); 43 static_assert(std::three_way_comparable<unsigned int volatile&&>); 44 static_assert(std::three_way_comparable<unsigned long const volatile&&>); 45 46 // with explicit ordering 47 static_assert(std::three_way_comparable<int, std::strong_ordering>); 48 static_assert(std::three_way_comparable<int, std::weak_ordering>); 49 static_assert(std::three_way_comparable<double, std::partial_ordering>); 50 static_assert(!std::three_way_comparable<double, std::weak_ordering>); 51 static_assert(std::three_way_comparable<void*, std::strong_ordering>); 52 static_assert(std::three_way_comparable<void*, std::weak_ordering>); 53 static_assert(std::three_way_comparable<char*, std::strong_ordering>); 54 static_assert(std::three_way_comparable<char*, std::weak_ordering>); 55 static_assert(std::three_way_comparable<char const*, std::strong_ordering>); 56 static_assert(std::three_way_comparable<char const*, std::weak_ordering>); 57 static_assert(std::three_way_comparable<char volatile*, std::strong_ordering>); 58 static_assert(std::three_way_comparable<char volatile*, std::weak_ordering>); 59 static_assert(std::three_way_comparable<char const volatile*, std::strong_ordering>); 60 static_assert(std::three_way_comparable<char const volatile*, std::weak_ordering>); 61 static_assert(std::three_way_comparable<wchar_t&, std::strong_ordering>); 62 static_assert(std::three_way_comparable<wchar_t&, std::weak_ordering>); 63 static_assert(std::three_way_comparable<char8_t const&, std::strong_ordering>); 64 static_assert(std::three_way_comparable<char8_t const&, std::weak_ordering>); 65 static_assert(std::three_way_comparable<char16_t volatile&, std::strong_ordering>); 66 static_assert(std::three_way_comparable<char16_t volatile&, std::weak_ordering>); 67 static_assert(std::three_way_comparable<char32_t const volatile&, std::strong_ordering>); 68 static_assert(std::three_way_comparable<char32_t const volatile&, std::weak_ordering>); 69 static_assert(std::three_way_comparable<unsigned char&&, std::strong_ordering>); 70 static_assert(std::three_way_comparable<unsigned char&&, std::weak_ordering>); 71 static_assert(std::three_way_comparable<unsigned short const&&, std::strong_ordering>); 72 static_assert(std::three_way_comparable<unsigned short const&&, std::weak_ordering>); 73 static_assert(std::three_way_comparable<unsigned int volatile&&, std::strong_ordering>); 74 static_assert(std::three_way_comparable<unsigned int volatile&&, std::weak_ordering>); 75 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::strong_ordering>); 76 static_assert(std::three_way_comparable<unsigned long const volatile&&, std::weak_ordering>); 77 78 static_assert(!std::three_way_comparable<int[5]>); 79 static_assert(!std::three_way_comparable<int (*)(int)>); 80 static_assert(!std::three_way_comparable<int (&)(int)>); 81 static_assert(!std::three_way_comparable<int (*)(int) noexcept>); 82 static_assert(!std::three_way_comparable<int (&)(int) noexcept>); 83 static_assert(!std::three_way_comparable<std::nullptr_t>); 84 static_assert(!std::three_way_comparable<void>); 85 86 struct S {}; 87 static_assert(!std::three_way_comparable<int S::*>); 88 static_assert(!std::three_way_comparable<int (S::*)()>); 89 static_assert(!std::three_way_comparable<int (S::*)() noexcept>); 90 static_assert(!std::three_way_comparable<int (S::*)() &>); 91 static_assert(!std::three_way_comparable<int (S::*)() & noexcept>); 92 static_assert(!std::three_way_comparable<int (S::*)() &&>); 93 static_assert(!std::three_way_comparable<int (S::*)() && noexcept>); 94 static_assert(!std::three_way_comparable<int (S::*)() const>); 95 static_assert(!std::three_way_comparable<int (S::*)() const noexcept>); 96 static_assert(!std::three_way_comparable<int (S::*)() const&>); 97 static_assert(!std::three_way_comparable<int (S::*)() const & noexcept>); 98 static_assert(!std::three_way_comparable<int (S::*)() const&&>); 99 static_assert(!std::three_way_comparable<int (S::*)() const && noexcept>); 100 static_assert(!std::three_way_comparable<int (S::*)() volatile>); 101 static_assert(!std::three_way_comparable<int (S::*)() volatile noexcept>); 102 static_assert(!std::three_way_comparable<int (S::*)() volatile&>); 103 static_assert(!std::three_way_comparable<int (S::*)() volatile & noexcept>); 104 static_assert(!std::three_way_comparable<int (S::*)() volatile&&>); 105 static_assert(!std::three_way_comparable<int (S::*)() volatile && noexcept>); 106 static_assert(!std::three_way_comparable<int (S::*)() const volatile>); 107 static_assert(!std::three_way_comparable<int (S::*)() const volatile noexcept>); 108 static_assert(!std::three_way_comparable<int (S::*)() const volatile&>); 109 static_assert(!std::three_way_comparable<int (S::*)() const volatile & noexcept>); 110 static_assert(!std::three_way_comparable<int (S::*)() const volatile&&>); 111 static_assert(!std::three_way_comparable<int (S::*)() const volatile && noexcept>); 112 } // namespace fundamentals 113 114 namespace user_defined { 115 116 struct S { 117 auto operator<=>(const S&) const = default; 118 }; 119 120 static_assert(std::three_way_comparable<S>); 121 static_assert(std::three_way_comparable<S, std::strong_ordering>); 122 static_assert(std::three_way_comparable<S, std::partial_ordering>); 123 124 struct SpaceshipNotDeclared { 125 }; 126 127 static_assert(!std::three_way_comparable<SpaceshipNotDeclared>); 128 129 struct SpaceshipDeleted { 130 auto operator<=>(const SpaceshipDeleted&) const = delete; 131 }; 132 133 static_assert(!std::three_way_comparable<SpaceshipDeleted>); 134 135 struct SpaceshipWithoutEqualityOperator { 136 auto operator<=>(const SpaceshipWithoutEqualityOperator&) const; 137 }; 138 139 static_assert(!std::three_way_comparable<SpaceshipWithoutEqualityOperator>); 140 141 struct EqualityOperatorDeleted { 142 bool operator==(const EqualityOperatorDeleted&) const = delete; 143 }; 144 145 static_assert(!std::three_way_comparable<EqualityOperatorDeleted>); 146 147 struct EqualityOperatorOnly { 148 bool operator==(const EqualityOperatorOnly&) const = default; 149 }; 150 151 static_assert(!std::three_way_comparable<EqualityOperatorOnly>); 152 153 struct SpaceshipDeclaredEqualityOperatorDeleted { 154 bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete; 155 auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default; 156 }; 157 158 static_assert(!std::three_way_comparable<SpaceshipDeclaredEqualityOperatorDeleted>); 159 160 struct AllInequalityOperators { 161 bool operator<(const AllInequalityOperators&) const; 162 bool operator<=(const AllInequalityOperators&) const; 163 bool operator>(const AllInequalityOperators&) const; 164 bool operator>=(const AllInequalityOperators&) const; 165 bool operator!=(const AllInequalityOperators&) const; 166 }; 167 168 static_assert(!std::three_way_comparable<AllInequalityOperators>); 169 170 struct AllComparisonOperators { 171 bool operator<(const AllComparisonOperators&) const; 172 bool operator<=(const AllComparisonOperators&) const; 173 bool operator>(const AllComparisonOperators&) const; 174 bool operator>=(const AllComparisonOperators&) const; 175 bool operator!=(const AllComparisonOperators&) const; 176 bool operator==(const AllComparisonOperators&) const; 177 }; 178 179 static_assert(!std::three_way_comparable<AllComparisonOperators>); 180 181 struct AllButOneInequalityOperators { 182 bool operator<(const AllButOneInequalityOperators&) const; 183 bool operator<=(const AllButOneInequalityOperators&) const; 184 bool operator>(const AllButOneInequalityOperators&) const; 185 bool operator!=(const AllButOneInequalityOperators&) const; 186 }; 187 188 static_assert(!std::three_way_comparable<AllButOneInequalityOperators>); 189 190 struct AllInequalityOperatorsOneDeleted { 191 bool operator<(const AllInequalityOperatorsOneDeleted&) const; 192 bool operator<=(const AllInequalityOperatorsOneDeleted&) const; 193 bool operator>(const AllInequalityOperatorsOneDeleted&) const; 194 bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete; 195 bool operator!=(const AllInequalityOperatorsOneDeleted&) const; 196 }; 197 198 static_assert(!std::three_way_comparable<AllInequalityOperatorsOneDeleted>); 199 200 struct EqualityOperatorWrongReturnType { 201 int operator==(const EqualityOperatorWrongReturnType&); 202 auto operator<=>(const EqualityOperatorWrongReturnType&) const = default; 203 }; 204 205 static_assert(!std::three_way_comparable<EqualityOperatorWrongReturnType>); 206 207 struct SpaceshipWrongReturnType { 208 bool operator==(const SpaceshipWrongReturnType&) const = default; 209 int operator<=>(const SpaceshipWrongReturnType&); 210 }; 211 212 static_assert(!std::three_way_comparable<SpaceshipWrongReturnType>); 213 214 struct EqualityOperatorNonConstArgument { 215 bool operator==(EqualityOperatorNonConstArgument&); 216 auto operator<=>(const EqualityOperatorNonConstArgument&) const = default; 217 }; 218 219 static_assert(!std::three_way_comparable<EqualityOperatorNonConstArgument>); 220 221 struct SpaceshipNonConstArgument { 222 bool operator==(const SpaceshipNonConstArgument&) const = default; 223 auto operator<=>(SpaceshipNonConstArgument&); 224 }; 225 226 static_assert(!std::three_way_comparable<SpaceshipNonConstArgument>); 227 } // namespace user_defined 228