Implement ranges::adjacent_find (#822)

This commit is contained in:
Casey Carter 2020-05-14 15:44:21 -07:00 коммит произвёл GitHub
Родитель 79c602144b
Коммит 995401051f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 124 добавлений и 0 удалений

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

@ -504,6 +504,46 @@ _NODISCARD _FwdIt adjacent_find(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt
#ifdef __cpp_lib_concepts
namespace ranges {
// VARIABLE ranges::adjacent_find
class _Adjacent_find_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;
template <forward_iterator _It, sentinel_for<_It> _Se, class _Pj = identity,
indirect_binary_predicate<projected<_It, _Pj>, projected<_It, _Pj>> _Pr = ranges::equal_to>
_NODISCARD constexpr _It operator()(_It _First, const _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const {
// find first satisfying _Pred with successor
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
if (_UFirst == _ULast) {
return _First;
}
for (auto _UNext = _UFirst;; _UFirst = _UNext) {
if (++_UNext == _ULast) {
_Seek_wrapped(_First, _UNext);
return _First;
}
if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, *_UNext))) {
_Seek_wrapped(_First, _UFirst);
return _First;
}
}
}
template <forward_range _Rng, class _Pj = identity,
indirect_binary_predicate<projected<iterator_t<_Rng>, _Pj>, projected<iterator_t<_Rng>, _Pj>> _Pr =
ranges::equal_to>
_NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const {
return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
}
};
inline constexpr _Adjacent_find_fn adjacent_find{_Not_quite_object::_Construct_tag{}};
// VARIABLE ranges::count
class _Count_fn : private _Not_quite_object {
public:

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

@ -542,6 +542,11 @@ void test_in() {
with_input_ranges<Instantiator>::call();
}
template <class Instantiator>
void test_fwd() {
with_forward_ranges<Instantiator>::call();
}
template <class Instantiator>
void test_in_in() {
with_input_ranges<with_input_ranges<Instantiator>>::call();

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

@ -231,6 +231,7 @@ tests\P0784R7_library_support_for_more_constexpr_containers
tests\P0811R3_midpoint_lerp
tests\P0896R4_P1614R2_comparisons
tests\P0896R4_ranges_algorithm_machinery
tests\P0896R4_ranges_alg_adjacent_find
tests\P0896R4_ranges_alg_all_of
tests\P0896R4_ranges_alg_any_of
tests\P0896R4_ranges_alg_copy

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

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\concepts_matrix.lst

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

@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <algorithm>
#include <array>
#include <cassert>
#include <concepts>
#include <ranges>
#include <utility>
//
#include <range_algorithm_support.hpp>
constexpr void smoke_test() {
using ranges::adjacent_find, ranges::iterator_t, std::same_as;
using P = std::pair<int, int>;
// Validate dangling story
STATIC_ASSERT(same_as<decltype(adjacent_find(borrowed<false>{}, ranges::equal_to{})), ranges::dangling>);
STATIC_ASSERT(same_as<decltype(adjacent_find(borrowed<true>{}, ranges::equal_to{})), int*>);
const std::array pairs = {P{0, 42}, P{1, 42}, P{2, 42}, P{4, 42}, P{5, 42}};
const auto pred = [](const int x, const int y) { return y - x > 1; };
{
// Validate range overload [found case]
const auto result = adjacent_find(pairs, pred, get_first);
STATIC_ASSERT(same_as<decltype(result), const iterator_t<decltype(pairs)>>);
assert(result == pairs.begin() + 2);
}
{
// Validate iterator + sentinel overload [found case]
const auto result = adjacent_find(pairs.begin(), pairs.end(), pred, get_first);
STATIC_ASSERT(same_as<decltype(result), const iterator_t<decltype(pairs)>>);
assert(result == pairs.begin() + 2);
}
{
// Validate range overload [not found case]
const auto result = adjacent_find(pairs, ranges::equal_to{}, get_first);
STATIC_ASSERT(same_as<decltype(result), const iterator_t<decltype(pairs)>>);
assert(result == pairs.end());
}
{
// Validate iterator + sentinel overload [not found case]
const auto result = adjacent_find(pairs.begin(), pairs.end(), ranges::equal_to{}, get_first);
STATIC_ASSERT(same_as<decltype(result), const iterator_t<decltype(pairs)>>);
assert(result == pairs.end());
}
}
int main() {
STATIC_ASSERT((smoke_test(), true));
smoke_test();
}
struct instantiator {
template <class Fwd>
static void call(Fwd&& fwd = {}) {
using ranges::adjacent_find, ranges::iterator_t;
(void) adjacent_find(fwd);
(void) adjacent_find(begin(fwd), end(fwd));
BinaryPredicateFor<iterator_t<Fwd>, iterator_t<Fwd>> pred{};
(void) adjacent_find(fwd, pred);
(void) adjacent_find(begin(fwd), end(fwd), pred);
ProjectedBinaryPredicate<0, 0> projpred{};
ProjectionFor<iterator_t<Fwd>, 0> proj{};
(void) adjacent_find(fwd, projpred, proj);
(void) adjacent_find(begin(fwd), end(fwd), projpred, proj);
}
};
template void test_fwd<instantiator>();