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

Implement ranges::swap_ranges #918

Merged
merged 70 commits into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
19c2a15
added the move algorithm on line 1265 of algorithm and created a new …
ahanamuk Jun 8, 2020
354e48b
added cmake file
ahanamuk Jun 8, 2020
09f6c9f
passing all tests for ranges move algorithm
ahanamuk Jun 8, 2020
61375a9
updated move algo tests to check that we actually move elems, not jus…
ahanamuk Jun 9, 2020
68640ed
enabled constexpr, cleaned up move algo test
ahanamuk Jun 9, 2020
5277552
removed iostream unused header
ahanamuk Jun 9, 2020
45fb14d
mainly updated formatting/comments based on feedback
ahanamuk Jun 10, 2020
80e349e
Delete cmake
ahanamuk Jun 10, 2020
d4f91b0
modified a test
ahanamuk Jun 11, 2020
a685197
Merge branch 'move_algo' of https://github.com/ahanamuk/STL
ahanamuk Jun 11, 2020
c9f134f
initial fill algo
ahanamuk Jun 11, 2020
93ff947
Passing all fill tests
ahanamuk Jun 11, 2020
be947f1
added a test case
ahanamuk Jun 11, 2020
5cb7bfc
minor changes/formatting updates to move
ahanamuk Jun 12, 2020
9170077
updated clang formatting
ahanamuk Jun 12, 2020
d4fbaac
initial fill algo
ahanamuk Jun 11, 2020
064684e
comitting untracked stuff
ahanamuk Jun 16, 2020
db97692
initial fill and fill_n algo commit
ahanamuk Jun 16, 2020
01ff2e9
working version of fill algo
ahanamuk Jun 16, 2020
ea9f61a
fixed up fill_n test
ahanamuk Jun 16, 2020
718624a
Merge branch 'master' into fill_algo_branch1
CaseyCarter Jun 16, 2020
d5c055e
Two bugs which are sortof Casey's fault
CaseyCarter Jun 16, 2020
3c89a33
Merge pull request #1 from CaseyCarter/fill
ahanamuk Jun 16, 2020
0462828
initial swap_ranges algo
ahanamuk Jun 18, 2020
ba38943
made changes based on initial PR comments
ahanamuk Jun 18, 2020
e416462
formatting update
ahanamuk Jun 22, 2020
879c307
initial swap_ranges algo
ahanamuk Jun 18, 2020
a5fb6d3
fixing merge conflicts
ahanamuk Jun 23, 2020
604020e
removed fill code
ahanamuk Jun 23, 2020
b862691
updated swap_ranges_result and tests
ahanamuk Jun 23, 2020
0859e3d
working on fixing tests
ahanamuk Jun 23, 2020
2bd5cc2
passing tests except STATIC_ASSERT smoke_test() line
ahanamuk Jun 24, 2020
f41b2f0
not really a change
ahanamuk Jun 24, 2020
6779e67
squash and rebase onto master
CaseyCarter Jun 24, 2020
1b73b14
merged with casey's updates
ahanamuk Jun 24, 2020
66a59e7
minor updates
ahanamuk Jun 24, 2020
30bfcd8
Revert inadvertent regression of LLVM reference
CaseyCarter Jun 24, 2020
6e3ed4e
first round of code review updates
ahanamuk Jul 1, 2020
49e5b52
more minor updates
ahanamuk Jul 1, 2020
82a66fa
removed fill code
ahanamuk Jun 23, 2020
3f79f08
updated swap_ranges_result and tests
ahanamuk Jun 23, 2020
93a33a7
working on fixing tests
ahanamuk Jun 23, 2020
90104de
passing tests except STATIC_ASSERT smoke_test() line
ahanamuk Jun 24, 2020
e349f54
not really a change
ahanamuk Jun 24, 2020
2b2abdb
Library support for C++20 coroutines (#894)
joemmett Jun 17, 2020
301bb37
Update VMSS pool to VS 2019 16.7 Preview 2 (#851)
cbezault Jun 20, 2020
1585269
<algorithm>: Implemented ranges::move (#888)
ahanamuk Jun 20, 2020
3e8e2a5
Updated _MSVC_STL_UPDATE macro (#897)
hikmatfarhat-ndu Jun 20, 2020
0d6b8a0
Cleanup ranges test machinery (#899)
CaseyCarter Jun 20, 2020
1bb78fc
Code cleanups in stl/src (#900)
StephanTLavavej Jun 20, 2020
9e74913
Implement ranges::_Ubegin and ranges::_Uend CPOs (#901)
CaseyCarter Jun 20, 2020
1a7d698
tests: Avoid dialog boxes, prevent stdout from being lost (#906)
StephanTLavavej Jun 20, 2020
ccd934b
P0896R4_P1614R2_comparisons/test.cpp: Increase test coverage for MSVC…
SuperWig Jun 24, 2020
86c45a6
Simplify span's representation (#877)
miscco Jun 24, 2020
85d03be
Implement ranges::is_permutation (#892)
CaseyCarter Jun 24, 2020
ed2e1ca
Internal headers have extension .hpp (#902)
CaseyCarter Jun 24, 2020
51c7b1a
Fix std::pow's "sufficient additional overloads" (#903)
Berrysoft Jun 24, 2020
d874e21
Require VS 2019 16.7 Preview 2 or later. (#911)
StephanTLavavej Jun 24, 2020
7e430e3
resolving merge conflicts
CaseyCarter Jun 24, 2020
a72b3b0
More code cleanups in stl/src (#912)
StephanTLavavej Jun 24, 2020
35b7876
squash and rebase onto master
CaseyCarter Jun 24, 2020
8898a05
minor updates
ahanamuk Jun 24, 2020
cbe9ebb
Revert inadvertent regression of LLVM reference
CaseyCarter Jun 24, 2020
7afa499
first round of code review updates
ahanamuk Jul 1, 2020
4ab8992
more minor updates
ahanamuk Jul 1, 2020
f382c41
Merge branch 'swap_ranges_algo' of https://github.com/ahanamuk/STL in…
ahanamuk Jul 1, 2020
eacdd67
Merge branch 'master' into swap_ranges_algo
ahanamuk Jul 1, 2020
ba1cebb
Restore CRLF line endings in tests/std/test.lst
CaseyCarter Jul 1, 2020
c973d28
Casey renamed `move_only_range` to `basic_borrowed_range`
CaseyCarter Jul 1, 2020
3e3e653
test::without_output_ranges::call should be constexpr
CaseyCarter Jul 2, 2020
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
45 changes: 45 additions & 0 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,51 @@ namespace ranges {
} // namespace ranges
#endif // __cpp_lib_concepts

#ifdef __cpp_lib_concepts
namespace ranges {
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
// ALIAS TEMPLATE swap_ranges_result
template <class _In1, class _In2>
using swap_ranges_result = in_in_result<_In1, _In2>;

// VARIABLE ranges::swap_ranges
class _Swap_ranges_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <input_iterator _It1, sentinel_for<_It1> _Se1, input_iterator _It2, sentinel_for<_It2> _Se2>
requires indirectly_swappable<_It1, _It2>
constexpr swap_ranges_result<_It1, _It2>
operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2) const {
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);
auto _UFirst1 = _Get_unwrapped(_STD move(_First1));
auto _ULast1 = _Get_unwrapped(_STD move(_Last1));
auto _UFirst2 = _Get_unwrapped(_STD move(_First2));
auto _ULast2 = _Get_unwrapped(_STD move(_Last2));
while ((_UFirst1 != _ULast1) && (_UFirst2 != _ULast2)) {
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
_RANGES iter_swap(_UFirst1, _UFirst2);
++_UFirst1; ++_UFirst2;
}

_Seek_wrapped(_First1, _STD move(_UFirst1));
_Seek_wrapped(_First2, _STD move(_UFirst2));
return {_STD move(_First1), _STD move(_First2)};
}

template <input_range _Rng1, input_range _Rng2>
requires indirectly_swappable<iterator_t<_Rng1>, iterator_t<_Rng2>>
constexpr swap_ranges_result<borrowed_iterator_t<_Rng1>, borrowed_iterator_t<_Rng2>>
operator()(_Rng1&& _Range1, _Rng2&& _Range2) const {
return (*this)(_RANGES begin(_Range1), _RANGES end(_Range1), _RANGES begin(_Range2), _RANGES end(_Range2));
}
// clang-format on
};

inline constexpr _Swap_ranges_fn swap_ranges{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATE swap_ranges
template <class _FwdIt1, class _FwdIt2>
_CONSTEXPR20 _FwdIt2 swap_ranges(const _FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) {
Expand Down
140 changes: 140 additions & 0 deletions tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,141 @@ struct with_input_ranges {
}
};

template <class Continuation, class Element = int>
struct with_output_ranges {
template <class... Args>
static void call() {
using namespace test;

// For all ranges, IsCommon implies Eq.
// For single-pass ranges, Eq is uninteresting without IsCommon (there's only one valid iterator
// value at a time, and no reason to compare it with itself for equality).
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::no, Common::no, CanCompare::no, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::no, Common::no, CanCompare::no, ProxyRef::yes>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();

Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::yes>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::no, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();

Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::no, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::no, ProxyRef::yes>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();

Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::no, ProxyRef::yes>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<output, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();

// forward always has Eq; !IsSized && Diff is uninteresting (sized_range is sized_range).
Continuation::template call<Args...,
range<fwd, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<fwd, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();

// Ditto always Eq; !IsSized && Diff is uninteresting (ranges::size still works).
Continuation::template call<Args...,
range<bidi, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::no, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<bidi, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();

// Ditto always Eq; !IsSized && SizedSentinel is uninteresting (ranges::size works either way), as is
// !IsSized && IsCommon.
Continuation::template call<Args...,
range<random, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<random, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::yes>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<random, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::yes>>();

// Ditto always Eq; !IsSized && SizedSentinel is uninteresting (ranges::size still works), as is
// !IsSized && IsCommon. contiguous also implies !Proxy.
Continuation::template call<Args...,
range<contiguous, Element, Sized::no, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<contiguous, Element, Sized::yes, CanDifference::no, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<contiguous, Element, Sized::yes, CanDifference::no, Common::yes, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<contiguous, Element, Sized::yes, CanDifference::yes, Common::no, CanCompare::yes, ProxyRef::no>>();
Continuation::template call<Args...,
range<contiguous, Element, Sized::yes, CanDifference::yes, Common::yes, CanCompare::yes, ProxyRef::no>>();
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
}
};

template <class Continuation, class Element = int>
struct with_forward_ranges {
template <class... Args>
Expand Down Expand Up @@ -843,6 +978,11 @@ struct with_difference {
}
};

template <class Instantiator, class Element = int>
constexpr void test_out() {
with_output_ranges<Instantiator, Element>::call();
}

template <class Instantiator, class Element = int>
constexpr void test_in() {
with_input_ranges<Instantiator, Element>::call();
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ tests\P0896R4_ranges_alg_mismatch
tests\P0896R4_ranges_alg_move
tests\P0896R4_ranges_alg_none_of
tests\P0896R4_ranges_alg_search
tests\P0896R4_ranges_alg_swap_ranges
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
tests\P0896R4_ranges_iterator_machinery
tests\P0896R4_ranges_range_machinery
tests\P0896R4_ranges_subrange
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_swap_ranges/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
67 changes: 67 additions & 0 deletions tests/std/tests/P0896R4_ranges_alg_swap_ranges/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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::swap_ranges, ranges::swap_ranges_result, ranges::iterator_t;
using std::same_as;
using I1 = iterator_t<move_only_range<int>>;
using I2 = iterator_t<move_only_range<int>>;
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved

// Validate that swap_ranges_result aliases in_in_result
STATIC_ASSERT(same_as<ranges::swap_ranges_result<int, double>, ranges::in_in_result<int, double>>);
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved

{ // Validate ranges overload
using R = std::array<int, 3>;
R range1 = {13, 53, 1876};
R range2 = {34, 243, 9366};
int const expected_output1[] = {34, 243, 9366};
int const expected_output2[] = {13, 53, 1876};
auto result = swap_ranges(move_only_range{range1}, move_only_range{range2});
STATIC_ASSERT(same_as<decltype(result), swap_ranges_result<I1, I2>>);
assert(result.in1 == move_only_range{range1}.end());
assert(result.in2 == move_only_range{range2}.end());
assert(ranges::equal(range1, expected_output1));
assert(ranges::equal(range2, expected_output2));
}
{ // Validate iterator + sentinel overload
int range1[] = {13, 53, 1876};
int range2[] = {34, 243, 9366};
move_only_range wrapped_range1{range1};
move_only_range wrapped_range2{range2};
int const expected_output1[] = {34, 243, 9366};
int const expected_output2[] = {13, 53, 1876};
auto result =
swap_ranges(wrapped_range1.begin(), wrapped_range1.end(), wrapped_range2.begin(), wrapped_range2.end());
STATIC_ASSERT(same_as<decltype(result), swap_ranges_result<I1, I2>>);
assert(result.in1 == wrapped_range1.end());
assert(result.in2 == wrapped_range2.end());
assert(ranges::equal(range1, expected_output1));
assert(ranges::equal(range2, expected_output2));
}
}

int main() {
#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-938163
STATIC_ASSERT((smoke_test(), true));
#endif // TRANSITION
ahanamuk marked this conversation as resolved.
Show resolved Hide resolved
smoke_test();
}

struct instantiator {
template <class In1, class In2>
static void call(In1 in1 = {}, In2 in2 = {}) {
(void) ranges::swap_ranges(in1, in2);
(void) ranges::swap_ranges(ranges::begin(in1), ranges::end(in1), ranges::begin(in2), ranges::end(in2));
}
};

template void test_in_in<instantiator>();