Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<algorithm>: Implemented ranges::move #888

Merged
merged 24 commits into from
Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,46 @@ namespace ranges {
} // namespace ranges
#endif // __cpp_lib_concepts

#ifdef __cpp_lib_concepts
namespace ranges {
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
// ALIAS TEMPLATE move_result
template <class _In, class _Out>
using move_result = in_out_result<_In, _Out>;

// VARIABLE ranges::move
class _Move_fn : private _Not_quite_object {
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <input_iterator _It, sentinel_for<_It> _Se, weakly_incrementable _Out>
requires indirectly_movable<_It, _Out>
constexpr move_result<_It, _Out> operator()(
_It _First, _Se _Last, _Out _Result) const {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_STD move(_First));
const auto _ULast = _Get_unwrapped(_STD move(_Last));
for (; _UFirst != _ULast; ++_UFirst, (void) ++_Result) {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
*_Result = _RANGES iter_move(_UFirst);
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
}

_Seek_wrapped(_First, _STD move(_UFirst));
return {_STD move(_First), _STD move(_Result)};
}

template <input_range _Rng, weakly_incrementable _Out>
requires indirectly_movable<iterator_t<_Rng>, _Out>
constexpr move_result<borrowed_iterator_t<_Rng>, _Out>
operator()(_Rng&& _Range, _Out _Result) const {
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _STD move(_Result));
}
// clang-format on
};

inline constexpr _Move_fn move{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATE partition_copy
template <class _InIt, class _OutIt1, class _OutIt2, class _Pr>
_CONSTEXPR20 pair<_OutIt1, _OutIt2> partition_copy(
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ tests\P0896R4_ranges_alg_find_if_not
tests\P0896R4_ranges_alg_for_each
tests\P0896R4_ranges_alg_for_each_n
tests\P0896R4_ranges_alg_mismatch
tests\P0896R4_ranges_alg_move
tests\P0896R4_ranges_alg_none_of
tests\P0896R4_ranges_iterator_machinery
tests\P0896R4_ranges_range_machinery
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_move/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_matrix.lst
81 changes: 81 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_move/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
#include <cassert>
#include <concepts>
#include <ranges>
#include <utility>
#include <range_algorithm_support.hpp>

struct int_wrapper {
int val = 10;
constexpr int_wrapper() = default;
constexpr int_wrapper(int x) : val{x} {}
constexpr int_wrapper(int_wrapper&& that) : val{std::exchange(that.val, -1)} {}
constexpr int_wrapper& operator=(int_wrapper&& that) {
val = std::exchange(that.val, -1);
return *this;
}
};

constexpr void smoke_test() {
using ranges::move, ranges::move_result, ranges::iterator_t;
using std::same_as;

// Validate that move_result aliases in_out_result
STATIC_ASSERT(same_as<move_result<int, double>, ranges::in_out_result<int, double>>);

// Validate dangling story
STATIC_ASSERT(same_as<decltype(move(borrowed<false>{}, static_cast<int*>(nullptr))), move_result<ranges::dangling, int*>>);
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
STATIC_ASSERT(same_as<decltype(move(borrowed<true>{}, static_cast<int*>(nullptr))), move_result<int*, int*>>);

int const input[] = {13, 53, 12435};
{
int output[] = {-1, -1, -1};
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
auto result = move(move_only_range{input}, move_only_range{output}.begin());
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
STATIC_ASSERT(same_as<decltype(result),
move_result<iterator_t<move_only_range<int const>>, iterator_t<move_only_range<int>>>>);
assert(result.in == move_only_range{input}.end());
assert(result.out == move_only_range{output}.end());
assert(ranges::equal(output, input));
}
{
int output[] = {-1, -1, -1};
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
move_only_range wrapped_input{input};
auto result = move(wrapped_input.begin(), wrapped_input.end(), move_only_range{output}.begin());
STATIC_ASSERT(same_as<decltype(result), move_result<iterator_t<move_only_range<int const>>, iterator_t<move_only_range<int>>>>);
assert(result.in == wrapped_input.end());
assert(result.out == move_only_range{output}.end());
assert(ranges::equal(output, input));
}
{
int_wrapper input1[3] = {13, 55, 1234};
int expected_output[3] = {13, 55, 1234};
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
int_wrapper actual_output[3] = {-1, -1, -1};
move_only_range wrapped_input{input1};
auto result = move(wrapped_input.begin(), wrapped_input.end(), move_only_range{actual_output}.begin());
assert(result.in == wrapped_input.end());
assert(result.out == move_only_range{actual_output}.end());
for (int i = 0; i < 3; ++i) {
assert(input1[i].val == -1);
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
assert(actual_output[i].val == expected_output[i]);
}
}

}

int main() {
STATIC_ASSERT((smoke_test(), true));
smoke_test();
}

struct instantiator {
template <class In, class Out>
static void call(In&& in = {}, Out out = {}) {
(void) ranges::move(in, std::move(out));
(void) ranges::move(ranges::begin(in), ranges::end(in), std::move(out));
}
};

template void test_in_out<instantiator>();