forked from OSchip/llvm-project
[libc++][compare] Implement three_way_comparable[_with] concepts
Implementation of `three_way_comparable` and `three_way_comparable_with` concepts from <compare> header. Please note that I have temporarily removed `<compare>` header from `<utility>` due to cyclic dependency that prevents using `<concepts>` header in `<compare>` one. I tried to quickly resolve those issues including applying suggestions from @cjdb and dive deeper by myself but the problem seems more complicated that we thought initially. I am in progress to prepare the patch with resolving this cyclic dependency between headers but for now I decided to put all that I have to the review to unblock people that depend on that functionality. At first glance the patch with resolving cyclic dependency is not so small (unless I find the way to make it smaller and cleaner) so I don't want to mix everything to one review. Reviewed By: ldionne, cjdb, #libc, Quuxplusone Differential Revision: https://reviews.llvm.org/D103478
This commit is contained in:
parent
1a88bd68c1
commit
8ce2675b13
libcxx
include
test
libcxx/diagnostics/detail.headers/compare
std/language.support/cmp/cmp.concept
|
@ -103,6 +103,7 @@ set(files
|
|||
__compare/common_comparison_category.h
|
||||
__compare/compare_three_way_result.h
|
||||
__compare/ordering.h
|
||||
__compare/three_way_comparable.h
|
||||
__concepts/arithmetic.h
|
||||
__concepts/assignable.h
|
||||
__concepts/boolean_testable.h
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H
|
||||
#define _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H
|
||||
|
||||
#include <__compare/common_comparison_category.h>
|
||||
#include <__compare/ordering.h>
|
||||
#include <__concepts/common_reference_with.h>
|
||||
#include <__concepts/equality_comparable.h>
|
||||
#include <__concepts/same_as.h>
|
||||
#include <__concepts/totally_ordered.h>
|
||||
#include <__config>
|
||||
#include <type_traits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) && !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
template<class _Tp, class _Cat>
|
||||
concept __compares_as =
|
||||
same_as<common_comparison_category_t<_Tp, _Cat>, _Cat>;
|
||||
|
||||
template<class _Tp, class _Cat = partial_ordering>
|
||||
concept three_way_comparable =
|
||||
__weakly_equality_comparable_with<_Tp, _Tp> &&
|
||||
__partially_ordered_with<_Tp, _Tp> &&
|
||||
requires(__make_const_lvalue_ref<_Tp> __a, __make_const_lvalue_ref<_Tp> __b) {
|
||||
{ __a <=> __b } -> __compares_as<_Cat>;
|
||||
};
|
||||
|
||||
template<class _Tp, class _Up, class _Cat = partial_ordering>
|
||||
concept three_way_comparable_with =
|
||||
three_way_comparable<_Tp, _Cat> &&
|
||||
three_way_comparable<_Up, _Cat> &&
|
||||
common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
|
||||
three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
|
||||
__weakly_equality_comparable_with<_Tp, _Up> &&
|
||||
__partially_ordered_with<_Tp, _Up> &&
|
||||
requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
|
||||
{ __t <=> __u } -> __compares_as<_Cat>;
|
||||
{ __u <=> __t } -> __compares_as<_Cat>;
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) && !defined(_LIBCPP_HAS_NO_CONCEPTS)
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___COMPARE_THREE_WAY_COMPARABLE_H
|
|
@ -35,6 +35,12 @@ namespace std {
|
|||
template<class... Ts>
|
||||
using common_comparison_category_t = typename common_comparison_category<Ts...>::type;
|
||||
|
||||
// [cmp.concept], concept three_way_comparable
|
||||
template<class T, class Cat = partial_ordering>
|
||||
concept three_way_comparable = see below;
|
||||
template<class T, class U, class Cat = partial_ordering>
|
||||
concept three_way_comparable_with = see below;
|
||||
|
||||
// [cmp.result], result of three-way comparison
|
||||
template<class T, class U = T> struct compare_three_way_result;
|
||||
|
||||
|
@ -129,6 +135,7 @@ namespace std {
|
|||
#include <__compare/common_comparison_category.h>
|
||||
#include <__compare/compare_three_way_result.h>
|
||||
#include <__compare/ordering.h>
|
||||
#include <__compare/three_way_comparable.h>
|
||||
#include <__config>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
|
|
|
@ -370,6 +370,7 @@ module std [system] {
|
|||
module common_comparison_category { private header "__compare/common_comparison_category.h" }
|
||||
module compare_three_way_result { private header "__compare/compare_three_way_result.h" }
|
||||
module ordering { private header "__compare/ordering.h" }
|
||||
module three_way_comparable { private header "__compare/three_way_comparable.h" }
|
||||
}
|
||||
}
|
||||
module complex {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: modules-build
|
||||
|
||||
// WARNING: This test was generated by 'generate_private_header_tests.py'
|
||||
// and should not be edited manually.
|
||||
|
||||
// expected-error@*:* {{use of private header from outside its module: '__compare/three_way_comparable.h'}}
|
||||
#include <__compare/three_way_comparable.h>
|
|
@ -0,0 +1,226 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
|
||||
// template<class T, class Cat = partial_ordering>
|
||||
// concept three_way_comparable = // see below
|
||||
|
||||
#include <compare>
|
||||
|
||||
#include "compare_types.h"
|
||||
|
||||
namespace fundamentals {
|
||||
// with default ordering
|
||||
static_assert(std::three_way_comparable<int>);
|
||||
static_assert(std::three_way_comparable<double>);
|
||||
static_assert(std::three_way_comparable<void*>);
|
||||
static_assert(std::three_way_comparable<char*>);
|
||||
static_assert(std::three_way_comparable<char const*>);
|
||||
static_assert(std::three_way_comparable<char volatile*>);
|
||||
static_assert(std::three_way_comparable<char const volatile*>);
|
||||
static_assert(std::three_way_comparable<wchar_t&>);
|
||||
#ifndef _LIBCPP_HAS_NO_CHAR8_T
|
||||
static_assert(std::three_way_comparable<char8_t const&>);
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
|
||||
static_assert(std::three_way_comparable<char16_t volatile&>);
|
||||
static_assert(std::three_way_comparable<char32_t const volatile&>);
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_INT128
|
||||
static_assert(std::three_way_comparable<__int128_t const&>);
|
||||
static_assert(std::three_way_comparable<__uint128_t const&>);
|
||||
#endif
|
||||
static_assert(std::three_way_comparable<unsigned char&&>);
|
||||
static_assert(std::three_way_comparable<unsigned short const&&>);
|
||||
static_assert(std::three_way_comparable<unsigned int volatile&&>);
|
||||
static_assert(std::three_way_comparable<unsigned long const volatile&&>);
|
||||
|
||||
// with explicit ordering
|
||||
static_assert(std::three_way_comparable<int, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<int, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<double, std::partial_ordering>);
|
||||
static_assert(!std::three_way_comparable<double, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<void*, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<void*, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char*, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char*, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char const*, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char const*, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char volatile*, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char volatile*, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char const volatile*, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char const volatile*, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<wchar_t&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<wchar_t&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char8_t const&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char8_t const&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char16_t volatile&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char16_t volatile&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<char32_t const volatile&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<char32_t const volatile&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned char&&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned char&&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned short const&&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned short const&&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned int volatile&&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned int volatile&&, std::weak_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned long const volatile&&, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<unsigned long const volatile&&, std::weak_ordering>);
|
||||
|
||||
static_assert(!std::three_way_comparable<int[5]>);
|
||||
static_assert(!std::three_way_comparable<int (*)(int)>);
|
||||
static_assert(!std::three_way_comparable<int (&)(int)>);
|
||||
static_assert(!std::three_way_comparable<int (*)(int) noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (&)(int) noexcept>);
|
||||
static_assert(!std::three_way_comparable<std::nullptr_t>);
|
||||
static_assert(!std::three_way_comparable<void>);
|
||||
|
||||
struct S {};
|
||||
static_assert(!std::three_way_comparable<int S::*>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)()>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() &>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() & noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() &&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() && noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const & noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const&&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const && noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile & noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile&&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() volatile && noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile & noexcept>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile&&>);
|
||||
static_assert(!std::three_way_comparable<int (S::*)() const volatile && noexcept>);
|
||||
} // namespace fundamentals
|
||||
|
||||
namespace user_defined {
|
||||
|
||||
struct S {
|
||||
auto operator<=>(const S&) const = default;
|
||||
};
|
||||
|
||||
static_assert(std::three_way_comparable<S>);
|
||||
static_assert(std::three_way_comparable<S, std::strong_ordering>);
|
||||
static_assert(std::three_way_comparable<S, std::partial_ordering>);
|
||||
|
||||
struct SpaceshipNotDeclared {
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipNotDeclared>);
|
||||
|
||||
struct SpaceshipDeleted {
|
||||
auto operator<=>(const SpaceshipDeleted&) const = delete;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipDeleted>);
|
||||
|
||||
struct SpaceshipWithoutEqualityOperator {
|
||||
auto operator<=>(const SpaceshipWithoutEqualityOperator&) const;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipWithoutEqualityOperator>);
|
||||
|
||||
struct EqualityOperatorDeleted {
|
||||
bool operator==(const EqualityOperatorDeleted&) const = delete;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<EqualityOperatorDeleted>);
|
||||
|
||||
struct EqualityOperatorOnly {
|
||||
bool operator==(const EqualityOperatorOnly&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<EqualityOperatorOnly>);
|
||||
|
||||
struct SpaceshipDeclaredEqualityOperatorDeleted {
|
||||
bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete;
|
||||
auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipDeclaredEqualityOperatorDeleted>);
|
||||
|
||||
struct AllInequalityOperators {
|
||||
bool operator<(const AllInequalityOperators&) const;
|
||||
bool operator<=(const AllInequalityOperators&) const;
|
||||
bool operator>(const AllInequalityOperators&) const;
|
||||
bool operator>=(const AllInequalityOperators&) const;
|
||||
bool operator!=(const AllInequalityOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<AllInequalityOperators>);
|
||||
|
||||
struct AllComparisonOperators {
|
||||
bool operator<(const AllComparisonOperators&) const;
|
||||
bool operator<=(const AllComparisonOperators&) const;
|
||||
bool operator>(const AllComparisonOperators&) const;
|
||||
bool operator>=(const AllComparisonOperators&) const;
|
||||
bool operator!=(const AllComparisonOperators&) const;
|
||||
bool operator==(const AllComparisonOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<AllComparisonOperators>);
|
||||
|
||||
struct AllButOneInequalityOperators {
|
||||
bool operator<(const AllButOneInequalityOperators&) const;
|
||||
bool operator<=(const AllButOneInequalityOperators&) const;
|
||||
bool operator>(const AllButOneInequalityOperators&) const;
|
||||
bool operator!=(const AllButOneInequalityOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<AllButOneInequalityOperators>);
|
||||
|
||||
struct AllInequalityOperatorsOneDeleted {
|
||||
bool operator<(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator<=(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator>(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete;
|
||||
bool operator!=(const AllInequalityOperatorsOneDeleted&) const;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<AllInequalityOperatorsOneDeleted>);
|
||||
|
||||
struct EqualityOperatorWrongReturnType {
|
||||
int operator==(const EqualityOperatorWrongReturnType&);
|
||||
auto operator<=>(const EqualityOperatorWrongReturnType&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<EqualityOperatorWrongReturnType>);
|
||||
|
||||
struct SpaceshipWrongReturnType {
|
||||
bool operator==(const SpaceshipWrongReturnType&) const = default;
|
||||
int operator<=>(const SpaceshipWrongReturnType&);
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipWrongReturnType>);
|
||||
|
||||
struct EqualityOperatorNonConstArgument {
|
||||
bool operator==(EqualityOperatorNonConstArgument&);
|
||||
auto operator<=>(const EqualityOperatorNonConstArgument&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<EqualityOperatorNonConstArgument>);
|
||||
|
||||
struct SpaceshipNonConstArgument {
|
||||
bool operator==(const SpaceshipNonConstArgument&) const = default;
|
||||
auto operator<=>(SpaceshipNonConstArgument&);
|
||||
};
|
||||
|
||||
static_assert(!std::three_way_comparable<SpaceshipNonConstArgument>);
|
||||
} // namespace user_defined
|
|
@ -0,0 +1,227 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: libcpp-no-concepts
|
||||
|
||||
// template<class T, class U, class Cat = partial_ordering>
|
||||
// concept three_way_comparable_with = // see below
|
||||
|
||||
#include <compare>
|
||||
|
||||
#include "compare_types.h"
|
||||
|
||||
template <class T, class U = T, typename Cat = std::partial_ordering>
|
||||
constexpr bool check_three_way_comparable_with() {
|
||||
constexpr bool result = std::three_way_comparable_with<T, U, Cat>;
|
||||
static_assert(std::three_way_comparable_with<U, T, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T, U const&&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const, U const&&, Cat> == result);
|
||||
if constexpr (!std::is_void_v<T>) {
|
||||
static_assert(std::three_way_comparable_with<T&, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T&, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T&, U const&&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&, U const&&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T&&, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&&, U const, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T&&, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&&, U const&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T&&, U const&&, Cat> == result);
|
||||
static_assert(std::three_way_comparable_with<T const&&, U const&&, Cat> == result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace fundamentals {
|
||||
static_assert(check_three_way_comparable_with<int, int>());
|
||||
static_assert(check_three_way_comparable_with<int, char>());
|
||||
static_assert(!check_three_way_comparable_with<int, unsigned int>());
|
||||
static_assert(check_three_way_comparable_with<int, double>());
|
||||
static_assert(check_three_way_comparable_with<int*, int*>());
|
||||
|
||||
static_assert(check_three_way_comparable_with<int, int, std::strong_ordering>());
|
||||
static_assert(check_three_way_comparable_with<int, char, std::strong_ordering>());
|
||||
static_assert(check_three_way_comparable_with<int, short, std::strong_ordering>());
|
||||
|
||||
static_assert(check_three_way_comparable_with<int, int, std::weak_ordering>());
|
||||
static_assert(check_three_way_comparable_with<int, char, std::weak_ordering>());
|
||||
static_assert(!check_three_way_comparable_with<int, unsigned int, std::weak_ordering>());
|
||||
|
||||
static_assert(!check_three_way_comparable_with<int, bool>());
|
||||
static_assert(!check_three_way_comparable_with<int, int*>());
|
||||
static_assert(!check_three_way_comparable_with<int, int[5]>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (*)()>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (&)()>());
|
||||
struct S {};
|
||||
static_assert(!check_three_way_comparable_with<int, int S::*>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)()>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() &>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() & noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const & noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile & noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile & noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() &&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() && noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const&&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const&& noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() volatile&& noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&&>());
|
||||
static_assert(!check_three_way_comparable_with<int, int (S::*)() const volatile&& noexcept>());
|
||||
static_assert(!check_three_way_comparable_with<int*, int[5]>());
|
||||
static_assert(!check_three_way_comparable_with<int[5], int[5]>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int*>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int[5]>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int (*)()>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int (&)()>());
|
||||
static_assert(!check_three_way_comparable_with<std::nullptr_t, int (S::*)()>());
|
||||
static_assert(!check_three_way_comparable_with<void, int>());
|
||||
static_assert(!check_three_way_comparable_with<void, int*>());
|
||||
static_assert(!check_three_way_comparable_with<void, std::nullptr_t>());
|
||||
static_assert(!check_three_way_comparable_with<void, int[5]>());
|
||||
static_assert(!check_three_way_comparable_with<void, int (*)()>());
|
||||
static_assert(!check_three_way_comparable_with<void, int (&)()>());
|
||||
static_assert(!check_three_way_comparable_with<void, int S::*>());
|
||||
static_assert(!check_three_way_comparable_with<void, int (S::*)()>());
|
||||
} // namespace fundamentals
|
||||
|
||||
namespace user_defined {
|
||||
struct S {
|
||||
bool operator==(int) const;
|
||||
std::strong_ordering operator<=>(int) const;
|
||||
operator int() const;
|
||||
|
||||
bool operator==(const S&) const = default;
|
||||
auto operator<=>(const S&) const = default;
|
||||
};
|
||||
|
||||
static_assert(check_three_way_comparable_with<S, int>());
|
||||
static_assert(check_three_way_comparable_with<S, int, std::strong_ordering>());
|
||||
static_assert(check_three_way_comparable_with<S, int, std::weak_ordering>());
|
||||
|
||||
struct SpaceshipNotDeclared {
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipNotDeclared>());
|
||||
|
||||
struct SpaceshipDeleted {
|
||||
auto operator<=>(const SpaceshipDeleted&) const = delete;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipDeleted>());
|
||||
|
||||
struct SpaceshipWithoutEqualityOperator {
|
||||
auto operator<=>(const SpaceshipWithoutEqualityOperator&) const;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipWithoutEqualityOperator>());
|
||||
|
||||
struct EqualityOperatorDeleted {
|
||||
bool operator==(const EqualityOperatorDeleted&) const = delete;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<EqualityOperatorDeleted>());
|
||||
|
||||
struct EqualityOperatorOnly {
|
||||
bool operator==(const EqualityOperatorOnly&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<EqualityOperatorOnly>());
|
||||
|
||||
struct SpaceshipDeclaredEqualityOperatorDeleted {
|
||||
bool operator==(const SpaceshipDeclaredEqualityOperatorDeleted&) const = delete;
|
||||
auto operator<=>(const SpaceshipDeclaredEqualityOperatorDeleted&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipDeclaredEqualityOperatorDeleted>());
|
||||
|
||||
struct AllInequalityOperators {
|
||||
bool operator<(const AllInequalityOperators&) const;
|
||||
bool operator<=(const AllInequalityOperators&) const;
|
||||
bool operator>(const AllInequalityOperators&) const;
|
||||
bool operator>=(const AllInequalityOperators&) const;
|
||||
bool operator!=(const AllInequalityOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<AllInequalityOperators>());
|
||||
|
||||
struct AllComparisonOperators {
|
||||
bool operator<(const AllComparisonOperators&) const;
|
||||
bool operator<=(const AllComparisonOperators&) const;
|
||||
bool operator>(const AllComparisonOperators&) const;
|
||||
bool operator>=(const AllComparisonOperators&) const;
|
||||
bool operator!=(const AllComparisonOperators&) const;
|
||||
bool operator==(const AllComparisonOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<AllComparisonOperators>());
|
||||
|
||||
struct AllButOneInequalityOperators {
|
||||
bool operator<(const AllButOneInequalityOperators&) const;
|
||||
bool operator<=(const AllButOneInequalityOperators&) const;
|
||||
bool operator>(const AllButOneInequalityOperators&) const;
|
||||
bool operator!=(const AllButOneInequalityOperators&) const;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<AllButOneInequalityOperators>());
|
||||
|
||||
struct AllInequalityOperatorsOneDeleted {
|
||||
bool operator<(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator<=(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator>(const AllInequalityOperatorsOneDeleted&) const;
|
||||
bool operator>=(const AllInequalityOperatorsOneDeleted&) const = delete;
|
||||
bool operator!=(const AllInequalityOperatorsOneDeleted&) const;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<AllInequalityOperatorsOneDeleted>());
|
||||
|
||||
struct EqualityOperatorWrongReturnType {
|
||||
int operator==(const EqualityOperatorWrongReturnType&);
|
||||
auto operator<=>(const EqualityOperatorWrongReturnType&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<EqualityOperatorWrongReturnType>());
|
||||
|
||||
struct SpaceshipWrongReturnType {
|
||||
bool operator==(const SpaceshipWrongReturnType&) const = default;
|
||||
int operator<=>(const SpaceshipWrongReturnType&);
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipWrongReturnType>());
|
||||
|
||||
struct EqualityOperatorNonConstArgument {
|
||||
bool operator==(EqualityOperatorNonConstArgument&);
|
||||
auto operator<=>(const EqualityOperatorNonConstArgument&) const = default;
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<EqualityOperatorNonConstArgument>());
|
||||
|
||||
struct SpaceshipNonConstArgument {
|
||||
bool operator==(const SpaceshipNonConstArgument&) const = default;
|
||||
auto operator<=>(SpaceshipNonConstArgument&);
|
||||
};
|
||||
|
||||
static_assert(!check_three_way_comparable_with<SpaceshipNonConstArgument>());
|
||||
} // namespace user_defined
|
Loading…
Reference in New Issue