<xutility> lexicographical_compare_three_way (#515)

Works towards #64.
This commit is contained in:
Adam Bucior 2020-03-08 22:07:08 +01:00 коммит произвёл GitHub
Родитель b3976d3921
Коммит 26b06299b0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 142 добавлений и 0 удалений

Просмотреть файл

@ -4812,6 +4812,69 @@ _NODISCARD bool lexicographical_compare(
}
#endif // _HAS_CXX17
#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
// FUNCTION TEMPLATE lexicographical_compare_three_way
template <class _InIt1, class _InIt2, class _Cmp>
_NODISCARD constexpr auto lexicographical_compare_three_way(
_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2, _Cmp _Comp) -> decltype(_Comp(*_First1, *_First2)) {
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);
auto _UFirst1 = _Get_unwrapped(_First1);
const auto _ULast1 = _Get_unwrapped(_Last1);
auto _UFirst2 = _Get_unwrapped(_First2);
const auto _ULast2 = _Get_unwrapped(_Last2);
using _UIt1 = decltype(_UFirst1);
using _UIt2 = decltype(_UFirst2);
using _Ty1 = remove_const_t<remove_pointer_t<_UIt1>>;
using _Ty2 = remove_const_t<remove_pointer_t<_UIt2>>;
if constexpr (conjunction_v<is_same<_Cmp, compare_three_way>, is_pointer<_UIt1>, is_pointer<_UIt2>,
disjunction<
#ifdef __cpp_lib_byte
conjunction<is_same<_Ty1, byte>, is_same<_Ty2, byte>>,
#endif // __cpp_lib_byte
conjunction<_Is_character<_Ty1>, is_unsigned<_Ty1>, _Is_character<_Ty2>,
is_unsigned<_Ty2>>>>) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
const auto _Num1 = static_cast<size_t>(_ULast1 - _UFirst1);
const auto _Num2 = static_cast<size_t>(_ULast2 - _UFirst2);
const int _Ans = _CSTD memcmp(_UFirst1, _UFirst2, (_STD min)(_Num1, _Num2));
if (_Ans == 0) {
return _Num1 <=> _Num2;
} else {
return _Ans <=> 0;
}
}
}
for (;;) {
if (_UFirst1 == _ULast1) {
return _UFirst2 == _ULast2 ? strong_ordering::equal : strong_ordering::less;
}
if (_UFirst2 == _ULast2) {
return strong_ordering::greater;
}
if (const auto _CmpResult = _Comp(*_UFirst1, *_UFirst2); _CmpResult != 0) {
return _CmpResult;
}
++_UFirst1;
++_UFirst2;
}
}
template <class _InIt1, class _InIt2>
_NODISCARD constexpr auto lexicographical_compare_three_way(
_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2, _InIt2 _Last2) {
return _STD lexicographical_compare_three_way(_First1, _Last1, _First2, _Last2, compare_three_way{});
}
#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
// FUNCTION TEMPLATE find
template <class _Ty>
_NODISCARD constexpr bool _Within_limits(const _Ty& _Val, true_type, true_type, _Any_tag) { // signed _Elem, signed _Ty

Просмотреть файл

@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <algorithm>
#include <array>
#include <cassert>
#include <compare>
#include <type_traits>
@ -119,6 +121,74 @@ static_assert(test_common_type<std::strong_ordering, std::partial_ordering>());
static_assert(test_common_type<std::strong_ordering, std::weak_ordering>());
static_assert(test_common_type<std::strong_ordering, std::strong_ordering>());
#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
constexpr auto my_cmp_three_way = [](const auto& left, const auto& right) { return left <=> right; };
template <class Left, class Right>
constexpr auto compare(const Left& left, const Right& right) {
using std::begin, std::end;
auto ret = std::lexicographical_compare_three_way(begin(left), end(left), begin(right), end(right));
auto ret2 =
std::lexicographical_compare_three_way(begin(left), end(left), begin(right), end(right), my_cmp_three_way);
assert(ret == ret2);
return ret;
}
template <class Ty1, class Ty2 = Ty1>
constexpr bool test_algorithm2() {
std::array<Ty1, 4> original{{0, 1, 2, 3}};
std::array<Ty2, 4> same{{0, 1, 2, 3}};
std::array<Ty2, 4> sameSizeAndLesser{{0, 1, 1, 3}};
std::array<Ty2, 4> sameSizeAndGreater{{0, 1, 3, 3}};
std::array<Ty2, 3> shorter{{0, 1, 2}};
std::array<Ty2, 3> shorterAndGreater{{0, 2, 3}};
std::array<Ty2, 5> longer{{0, 1, 2, 3, 4}};
std::array<Ty2, 5> longerAndLesser{{0, 1, 2, 2, 4}};
assert(compare(original, original) == 0);
assert(compare(original, same) == 0);
assert(compare(same, original) == 0);
assert(compare(original, sameSizeAndLesser) > 0);
assert(compare(sameSizeAndLesser, original) < 0);
assert(compare(original, sameSizeAndGreater) < 0);
assert(compare(sameSizeAndGreater, original) > 0);
assert(compare(original, shorter) > 0);
assert(compare(shorter, original) < 0);
assert(compare(original, shorterAndGreater) < 0);
assert(compare(shorterAndGreater, original) > 0);
assert(compare(original, longer) < 0);
assert(compare(longer, original) > 0);
assert(compare(original, longerAndLesser) > 0);
assert(compare(longerAndLesser, original) < 0);
return true;
}
template <class Ty1>
void test_algorithm() {
static_assert(test_algorithm2<Ty1>());
assert(test_algorithm2<Ty1>());
}
template <class Ty1, class Ty2>
void test_algorithm() {
static_assert(test_algorithm2<Ty1, Ty2>());
static_assert(test_algorithm2<Ty2, Ty1>());
assert((test_algorithm2<Ty1, Ty2>()));
assert((test_algorithm2<Ty2, Ty1>()));
}
#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
int main() {
test_ord<comp::equal>(std::partial_ordering::equivalent);
test_ord<comp::less>(std::partial_ordering::less);
@ -133,4 +203,13 @@ int main() {
test_ord<comp::equal>(std::strong_ordering::equivalent);
test_ord<comp::less>(std::strong_ordering::less);
test_ord<comp::greater>(std::strong_ordering::greater);
#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
test_algorithm<int>();
test_algorithm<char>();
test_algorithm<unsigned char>();
test_algorithm<int, char>();
test_algorithm<int, unsigned char>();
test_algorithm<char, unsigned char>();
#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts)
}