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