STL/stl/inc/compare

434 строки
17 KiB
C++

// compare standard header (core)
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _COMPARE_
#define _COMPARE_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#if !_HAS_CXX20
#pragma message("The contents of <compare> are available only with C++20 or later.")
#else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv
#ifdef __cpp_lib_concepts
#include <concepts>
#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv
#include <xtr1common>
#endif // !__cpp_lib_concepts
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
using _Literal_zero = decltype(nullptr);
using _Compare_t = signed char;
// These "pretty" enumerator names are safe since they reuse names of user-facing entities.
enum class _Compare_eq : _Compare_t { equal = 0, equivalent = equal };
enum class _Compare_ord : _Compare_t { less = -1, greater = 1 };
enum class _Compare_ncmp : _Compare_t { unordered = -127 };
// CLASS partial_ordering
class partial_ordering {
public:
_NODISCARD constexpr explicit partial_ordering(const _Compare_eq _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
_NODISCARD constexpr explicit partial_ordering(const _Compare_ord _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
_NODISCARD constexpr explicit partial_ordering(const _Compare_ncmp _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
static const partial_ordering less;
static const partial_ordering equivalent;
static const partial_ordering greater;
static const partial_ordering unordered;
_NODISCARD friend constexpr bool operator==(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value == 0;
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const partial_ordering&, const partial_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}
_NODISCARD friend constexpr bool operator==(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 == _Val._Value;
}
_NODISCARD friend constexpr bool operator!=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator<(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value == static_cast<_Compare_t>(_Compare_ord::less);
}
_NODISCARD friend constexpr bool operator>(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value > 0;
}
_NODISCARD friend constexpr bool operator<=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value <= 0 && _Val._Is_ordered();
}
_NODISCARD friend constexpr bool operator>=(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val._Value >= 0;
}
_NODISCARD friend constexpr bool operator<(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 < _Val._Value;
}
_NODISCARD friend constexpr bool operator>(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 > _Val._Value && _Val._Is_ordered();
}
_NODISCARD friend constexpr bool operator<=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 <= _Val._Value;
}
_NODISCARD friend constexpr bool operator>=(_Literal_zero, const partial_ordering _Val) noexcept {
return 0 >= _Val._Value && _Val._Is_ordered();
}
#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr partial_ordering operator<=>(const partial_ordering _Val, _Literal_zero) noexcept {
return _Val;
}
_NODISCARD friend constexpr partial_ordering operator<=>(_Literal_zero, const partial_ordering _Val) noexcept {
return partial_ordering{static_cast<_Compare_ord>(-_Val._Value)};
}
#endif // __cpp_impl_three_way_comparison
private:
_NODISCARD constexpr bool _Is_ordered() const noexcept {
return _Value != static_cast<_Compare_t>(_Compare_ncmp::unordered);
}
_Compare_t _Value;
};
inline constexpr partial_ordering partial_ordering::less(_Compare_ord::less);
inline constexpr partial_ordering partial_ordering::equivalent(_Compare_eq::equivalent);
inline constexpr partial_ordering partial_ordering::greater(_Compare_ord::greater);
inline constexpr partial_ordering partial_ordering::unordered(_Compare_ncmp::unordered);
// CLASS weak_ordering
class weak_ordering {
public:
_NODISCARD constexpr explicit weak_ordering(const _Compare_eq _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
_NODISCARD constexpr explicit weak_ordering(const _Compare_ord _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
static const weak_ordering less;
static const weak_ordering equivalent;
static const weak_ordering greater;
constexpr operator partial_ordering() const noexcept {
return partial_ordering{static_cast<_Compare_ord>(_Value)};
}
_NODISCARD friend constexpr bool operator==(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value == 0;
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const weak_ordering&, const weak_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}
_NODISCARD friend constexpr bool operator==(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 == _Val._Value;
}
_NODISCARD friend constexpr bool operator!=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator<(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value < 0;
}
_NODISCARD friend constexpr bool operator>(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value > 0;
}
_NODISCARD friend constexpr bool operator<=(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value <= 0;
}
_NODISCARD friend constexpr bool operator>=(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val._Value >= 0;
}
_NODISCARD friend constexpr bool operator<(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 < _Val._Value;
}
_NODISCARD friend constexpr bool operator>(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 > _Val._Value;
}
_NODISCARD friend constexpr bool operator<=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 <= _Val._Value;
}
_NODISCARD friend constexpr bool operator>=(_Literal_zero, const weak_ordering _Val) noexcept {
return 0 >= _Val._Value;
}
#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr weak_ordering operator<=>(const weak_ordering _Val, _Literal_zero) noexcept {
return _Val;
}
_NODISCARD friend constexpr weak_ordering operator<=>(_Literal_zero, const weak_ordering _Val) noexcept {
return weak_ordering{static_cast<_Compare_ord>(-_Val._Value)};
}
#endif // __cpp_impl_three_way_comparison
private:
_Compare_t _Value;
};
inline constexpr weak_ordering weak_ordering::less(_Compare_ord::less);
inline constexpr weak_ordering weak_ordering::equivalent(_Compare_eq::equivalent);
inline constexpr weak_ordering weak_ordering::greater(_Compare_ord::greater);
// CLASS strong_ordering
class strong_ordering {
public:
_NODISCARD constexpr explicit strong_ordering(const _Compare_eq _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
_NODISCARD constexpr explicit strong_ordering(const _Compare_ord _Value_) noexcept
: _Value(static_cast<_Compare_t>(_Value_)) {}
static const strong_ordering less;
static const strong_ordering equal;
static const strong_ordering equivalent;
static const strong_ordering greater;
constexpr operator partial_ordering() const noexcept {
return partial_ordering{static_cast<_Compare_ord>(_Value)};
}
constexpr operator weak_ordering() const noexcept {
return weak_ordering{static_cast<_Compare_ord>(_Value)};
}
_NODISCARD friend constexpr bool operator==(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value == 0;
}
#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
#ifndef __clang__ // TRANSITION, LLVM-41991
_NODISCARD
#endif // TRANSITION, LLVM-41991
friend constexpr bool operator==(const strong_ordering&, const strong_ordering&) noexcept = default;
#else // ^^^ supports <=> and P1185 / supports neither vvv
_NODISCARD friend constexpr bool operator!=(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value != 0;
}
_NODISCARD friend constexpr bool operator==(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 == _Val._Value;
}
_NODISCARD friend constexpr bool operator!=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 != _Val._Value;
}
#endif // defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201902L
_NODISCARD friend constexpr bool operator<(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value < 0;
}
_NODISCARD friend constexpr bool operator>(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value > 0;
}
_NODISCARD friend constexpr bool operator<=(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value <= 0;
}
_NODISCARD friend constexpr bool operator>=(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val._Value >= 0;
}
_NODISCARD friend constexpr bool operator<(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 < _Val._Value;
}
_NODISCARD friend constexpr bool operator>(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 > _Val._Value;
}
_NODISCARD friend constexpr bool operator<=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 <= _Val._Value;
}
_NODISCARD friend constexpr bool operator>=(_Literal_zero, const strong_ordering _Val) noexcept {
return 0 >= _Val._Value;
}
#ifdef __cpp_impl_three_way_comparison
_NODISCARD friend constexpr strong_ordering operator<=>(const strong_ordering _Val, _Literal_zero) noexcept {
return _Val;
}
_NODISCARD friend constexpr strong_ordering operator<=>(_Literal_zero, const strong_ordering _Val) noexcept {
return strong_ordering{static_cast<_Compare_ord>(-_Val._Value)};
}
#endif // __cpp_impl_three_way_comparison
private:
_Compare_t _Value;
};
inline constexpr strong_ordering strong_ordering::less(_Compare_ord::less);
inline constexpr strong_ordering strong_ordering::equal(_Compare_eq::equal);
inline constexpr strong_ordering strong_ordering::equivalent(_Compare_eq::equivalent);
inline constexpr strong_ordering strong_ordering::greater(_Compare_ord::greater);
// FUNCTION is_eq
_NODISCARD constexpr bool is_eq(const partial_ordering _Comp) noexcept {
return _Comp == 0;
}
// FUNCTION is_neq
_NODISCARD constexpr bool is_neq(const partial_ordering _Comp) noexcept {
return _Comp != 0;
}
// FUNCTION is_lt
_NODISCARD constexpr bool is_lt(const partial_ordering _Comp) noexcept {
return _Comp < 0;
}
// FUNCTION is_lteq
_NODISCARD constexpr bool is_lteq(const partial_ordering _Comp) noexcept {
return _Comp <= 0;
}
// FUNCTION is_gt
_NODISCARD constexpr bool is_gt(const partial_ordering _Comp) noexcept {
return _Comp > 0;
}
// FUNCTION is_gteq
_NODISCARD constexpr bool is_gteq(const partial_ordering _Comp) noexcept {
return _Comp >= 0;
}
// ALIAS TEMPLATE common_comparison_category_t
enum _Comparison_category : unsigned char {
_Comparison_category_none = 1,
_Comparison_category_partial = 2,
_Comparison_category_weak = 4,
_Comparison_category_strong = 0,
};
template <class... _Types>
inline constexpr unsigned char _Classify_category =
_Comparison_category{(_Classify_category<_Types> | ... | _Comparison_category_strong)};
template <class _Ty>
inline constexpr unsigned char _Classify_category<_Ty> = _Comparison_category_none;
template <>
inline constexpr unsigned char _Classify_category<partial_ordering> = _Comparison_category_partial;
template <>
inline constexpr unsigned char _Classify_category<weak_ordering> = _Comparison_category_weak;
template <>
inline constexpr unsigned char _Classify_category<strong_ordering> = _Comparison_category_strong;
template <class... _Types>
using common_comparison_category_t =
conditional_t<(_Classify_category<_Types...> & _Comparison_category_none) != 0, void,
conditional_t<(_Classify_category<_Types...> & _Comparison_category_partial) != 0, partial_ordering,
conditional_t<(_Classify_category<_Types...> & _Comparison_category_weak) != 0, weak_ordering,
strong_ordering>>>;
template <class... _Types>
struct common_comparison_category {
using type = common_comparison_category_t<_Types...>;
};
#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
// clang-format off
template <class _Ty, class _Cat>
concept _Compares_as = same_as<common_comparison_category_t<_Ty, _Cat>, _Cat>;
template <class _Ty, class _Cat = partial_ordering>
concept three_way_comparable = _Half_equality_comparable<_Ty, _Ty> && _Half_ordered<_Ty, _Ty>
&& requires(const remove_reference_t<_Ty>& __a, const remove_reference_t<_Ty>& __b) {
{ __a <=> __b } -> _Compares_as<_Cat>;
};
template <class _Ty1, class _Ty2, class _Cat = partial_ordering>
concept three_way_comparable_with = three_way_comparable<_Ty1, _Cat> && three_way_comparable<_Ty2, _Cat>
&& common_reference_with<const remove_reference_t<_Ty1>&, const remove_reference_t<_Ty2>&>
&& three_way_comparable<common_reference_t<const remove_reference_t<_Ty1>&, const remove_reference_t<_Ty2>&>, _Cat>
&& _Weakly_equality_comparable_with<_Ty1, _Ty2> && _Partially_ordered_with<_Ty1, _Ty2>
&& requires(const remove_reference_t<_Ty1>& __t, const remove_reference_t<_Ty2>& __u) {
{ __t <=> __u } -> _Compares_as<_Cat>;
{ __u <=> __t } -> _Compares_as<_Cat>;
};
template <class _Ty1, class _Ty2 = _Ty1>
using compare_three_way_result_t =
decltype(_STD declval<const remove_reference_t<_Ty1>&>() <=> _STD declval<const remove_reference_t<_Ty2>&>());
template <class _Ty1, class _Ty2 = _Ty1>
struct compare_three_way_result {};
template <class _Ty1, class _Ty2>
requires requires { typename compare_three_way_result_t<_Ty1, _Ty2>; }
struct compare_three_way_result<_Ty1, _Ty2> {
using type = compare_three_way_result_t<_Ty1, _Ty2>;
};
struct compare_three_way {
template <class _Ty1, class _Ty2>
requires three_way_comparable_with<_Ty1, _Ty2> // TRANSITION, GH-489
constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
noexcept(noexcept(_STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right))) /* strengthened */ {
return _STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right);
}
using is_transparent = int;
};
// clang-format on
#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
// Other components not yet implemented
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _HAS_CXX20
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _COMPARE_