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