-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
[libc++] Implement
views::join_with
* Implement "P2441R2 `views::join_with`" (https://wg21.link/P2441R2) * Complete implementation of "P2711R1 Making multi-param constructors of views explicit" (https://wg21.link/P2711R1) * Complete implementation of "P2770R0 Stashing stashing iterators for proper flattening" (https://wg21.link/P2770R0)
1 parent
465bfd4
commit a9a1031
Showing
54 changed files
with
5,385 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
...ranges/range.adaptors/range.join.with/range.join.with.iterator/deref.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::iterator<Const>::operator* is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
char range[3][2] = {{'x', 'x'}, {'y', 'y'}, {'z', 'z'}}; | ||
char pattern[2] = {',', ' '}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
*view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
*std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
30 changes: 30 additions & 0 deletions
30
...xx/ranges/range.adaptors/range.join.with/range.join.with.iterator/eq.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::iterator<Const>::operator== is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
char16_t range[3][1] = {{u'x'}, {u'y'}, {u'z'}}; | ||
char16_t pattern[1] = {u'-'}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
(view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
28 changes: 28 additions & 0 deletions
28
...es/range.adaptors/range.join.with/range.join.with.iterator/iter_move.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::iterator<Const>::iter_move is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
long range[2][1] = {{0L}, {2L}}; | ||
long pattern[1] = {1L}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
iter_move(view.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
iter_move(std::as_const(view).begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
38 changes: 38 additions & 0 deletions
38
...ange.adaptors/range.join.with/range.join.with.iterator/no_unique_address.compile.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
// XFAIL: msvc && clang-17 | ||
|
||
// <ranges> | ||
|
||
// This test ensures that we use `[[no_unique_address]]` in `join_with_view::iterator`. | ||
|
||
#include <ranges> | ||
|
||
#include "test_iterators.h" | ||
#include "test_range.h" | ||
|
||
struct InputView : std::ranges::view_base { | ||
using Inner = test_range<forward_iterator>; | ||
|
||
cpp20_input_iterator<Inner*> begin(); | ||
sentinel_wrapper<cpp20_input_iterator<Inner*>> end(); | ||
}; | ||
|
||
static_assert(std::ranges::input_range<InputView>); | ||
static_assert(!std::ranges::forward_range<InputView>); | ||
|
||
struct Pattern : std::ranges::view_base { | ||
int* begin(); | ||
int* end(); | ||
}; | ||
|
||
static_assert(alignof(void*) == alignof(std::variant<int*, int*>)); // alignof(__parent_) == alignof(__inner_it_) | ||
static_assert(sizeof(std::ranges::iterator_t<std::ranges::join_with_view<InputView, Pattern>>) == | ||
sizeof(void*) + sizeof(std::variant<int*, int*>)); // sizeof(__parent_) + sizeof(__inner_it_) |
33 changes: 33 additions & 0 deletions
33
...nges/range.adaptors/range.join.with/range.join.with.overview/adaptor.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::views::join_with is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
|
||
void test() { | ||
int range[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; | ||
int pattern_base[2] = {-1, -1}; | ||
auto pattern = std::views::all(pattern_base); | ||
|
||
// clang-format off | ||
std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::views::join_with(range, pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
range | std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::views::reverse | std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
|
||
std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::views::join_with(range, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
range | std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::views::reverse | std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
35 changes: 35 additions & 0 deletions
35
...xx/ranges/range.adaptors/range.join.with/range.join.with.sentinel/eq.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::sentinel<Const>::operator== is marked as [[nodiscard]]. | ||
|
||
#include <array> | ||
#include <ranges> | ||
#include <utility> | ||
|
||
#include "test_iterators.h" | ||
#include "test_range.h" | ||
|
||
void test() { | ||
std::array<test_range<cpp20_input_iterator>, 0> range; | ||
std::array<int, 0> pattern; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
static_assert(!std::ranges::common_range<decltype(view)>); | ||
|
||
// clang-format off | ||
(view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
(std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
30 changes: 30 additions & 0 deletions
30
...bcxx/ranges/range.adaptors/range.join.with/range.join.with.view/base.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::base is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
int range[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; | ||
int pattern[2] = {-1, -1}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
view.base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::as_const(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::move(std::as_const(view)).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::move(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
28 changes: 28 additions & 0 deletions
28
...cxx/ranges/range.adaptors/range.join.with/range.join.with.view/begin.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::begin is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
int range[3][2] = {{1, 3}, {4, 6}, {7, 9}}; | ||
int pattern[1] = {-2}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
28 changes: 28 additions & 0 deletions
28
...ibcxx/ranges/range.adaptors/range.join.with/range.join.with.view/end.nodiscard.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// Test the libc++ extension that std::ranges::join_with_view::end is marked as [[nodiscard]]. | ||
|
||
#include <ranges> | ||
#include <utility> | ||
|
||
void test() { | ||
int range[3][2] = {{1, 2}, {4, 5}, {7, 8}}; | ||
int pattern[1] = {-3}; | ||
|
||
std::ranges::join_with_view view(range, pattern); | ||
|
||
// clang-format off | ||
view.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
std::as_const(view).end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} | ||
// clang-format on | ||
} |
40 changes: 40 additions & 0 deletions
40
...es/range.adaptors/range.join.with/range.join.with.view/no_unique_address.compile.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// XFAIL: msvc | ||
|
||
// <ranges> | ||
|
||
// This test ensures that we use `[[no_unique_address]]` in `join_with_view`. | ||
|
||
#include <ranges> | ||
#include <string> | ||
|
||
struct ForwardView : std::ranges::view_base { | ||
std::string* begin() const; | ||
std::string* end() const; | ||
}; | ||
|
||
static_assert(std::ranges::forward_range<ForwardView>); | ||
static_assert(std::is_reference_v<std::ranges::range_reference_t<ForwardView>>); | ||
|
||
struct Pattern : std::ranges::view_base { | ||
char* begin() const; | ||
char* end() const; | ||
}; | ||
|
||
template <class View> | ||
struct Test { | ||
[[no_unique_address]] View view; | ||
char c; | ||
}; | ||
|
||
static_assert(sizeof(Test<std::ranges::join_with_view<ForwardView, Pattern>>) == | ||
sizeof(std::ranges::join_with_view<ForwardView, Pattern>)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
.../std/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.default.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// iterator() = default; | ||
|
||
#include <ranges> | ||
|
||
#include <cassert> | ||
#include <initializer_list> | ||
#include <iterator> | ||
#include <type_traits> | ||
#include <utility> | ||
|
||
#include "../types.h" | ||
#include "test_comparisons.h" | ||
#include "test_iterators.h" | ||
|
||
constexpr bool test() { | ||
{ // `V` and `Pattern` model forward range | ||
using Inner = BasicVectorView<int, ViewProperties{}, forward_iterator>; | ||
using V = BasicVectorView<Inner, ViewProperties{}, forward_iterator>; | ||
using Pattern = Inner; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using ConstIter = std::ranges::iterator_t<const JWV>; | ||
|
||
Iter iter; | ||
assert(testEquality(iter, Iter{}, true)); | ||
|
||
ConstIter citer; | ||
assert(testEquality(citer, ConstIter{}, true)); | ||
assert(testEquality(iter, citer, true)); | ||
|
||
std::ranges::join_with_view<V, Pattern> jwv(V{Inner{1, 2}, Inner{2, 1}}, Pattern{3, 3}); | ||
Iter jwv_iter = jwv.begin(); | ||
ConstIter jwv_citer = std::as_const(jwv).begin(); | ||
assert(testEquality(jwv_iter, jwv_citer, true)); | ||
|
||
assert(testEquality(jwv_iter, iter, false)); | ||
assert(testEquality(jwv_iter, citer, false)); | ||
assert(testEquality(jwv_citer, iter, false)); | ||
assert(testEquality(jwv_citer, citer, false)); | ||
} | ||
|
||
{ // `InnerIter` is not default constructible (does not model forward iterator, JWV cannot be const-accessed) | ||
using Inner = BasicVectorView<char, ViewProperties{.common = false}, EqComparableInputIter>; | ||
using V = BasicVectorView<Inner, ViewProperties{.common = false}, forward_iterator>; | ||
using Pattern = BasicVectorView<char, ViewProperties{}, forward_iterator>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
|
||
Iter iter; | ||
assert(testEquality(iter, Iter{}, true)); | ||
|
||
std::ranges::join_with_view<V, Pattern> jwv(V{Inner{'a', 'b'}, Inner{'c', 'd'}}, Pattern{',', ' '}); | ||
Iter jwv_iter = jwv.begin(); | ||
assert(testEquality(jwv_iter, iter, false)); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
104 changes: 104 additions & 0 deletions
104
...td/ranges/range.adaptors/range.join.with/range.join.with.iterator/ctor.not_const.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// constexpr iterator(iterator<!Const> i) | ||
// requires Const && convertible_to<iterator_t<V>, OuterIter> && | ||
// convertible_to<iterator_t<InnerRng>, InnerIter> && | ||
// convertible_to<iterator_t<Pattern>, PatternIter>; | ||
|
||
#include <ranges> | ||
|
||
#include <cassert> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
|
||
constexpr bool test() { | ||
{ // Regular conversion from `!Const` to `Const` iterator | ||
std::vector<std::vector<int>> vec = {{1, 2}, {3, 4}, {5, 6}}; | ||
int pattern = 0; | ||
std::ranges::join_with_view jwv(vec, pattern); | ||
auto it = jwv.begin(); | ||
assert(*it == 1); | ||
|
||
using CIter = std::ranges::iterator_t<const decltype(jwv)>; | ||
const CIter cit1 = it; // `cit1` points to element of `V` | ||
assert(*cit1 == 1); | ||
assert(cit1 == it); | ||
|
||
std::ranges::advance(it, 2); | ||
assert(*it == 0); | ||
CIter cit2 = it; // `cit2` points to element of `Pattern` | ||
assert(*cit2 == 0); | ||
assert(cit2 == it); | ||
|
||
++it; | ||
assert(*it == 3); | ||
CIter cit3 = it; | ||
assert(*cit3 == 3); | ||
assert(cit3 == it); | ||
|
||
--cit3; | ||
assert(cit2 == cit3); | ||
} | ||
|
||
{ // Test conversion from `Const` to `!Const` (should be invalid) | ||
using V = std::vector<std::vector<int>>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!std::convertible_to<CIter, Iter>); | ||
static_assert(!std::constructible_from<Iter, CIter>); | ||
} | ||
|
||
{ // When `convertible_to<iterator_t<V>, OuterIter>` is not modeled | ||
using Inner = std::vector<short>; | ||
using V = ConstOppositeView<Inner>; | ||
using Pattern = std::ranges::single_view<short>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!std::convertible_to<CIter, Iter>); | ||
static_assert(!std::constructible_from<Iter, CIter>); | ||
} | ||
|
||
{ // When `convertible_to<iterator_t<InnerRng>, InnerIter>` is not modeled | ||
using Inner = ConstOppositeView<long>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::ranges::single_view<long>; | ||
using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!std::convertible_to<CIter, Iter>); | ||
static_assert(!std::constructible_from<Iter, CIter>); | ||
} | ||
|
||
{ // When `convertible_to<iterator_t<Pattern>, PatternIter>` is not modeled | ||
using V = std::vector<std::vector<long long>>; | ||
using Pattern = ConstOppositeView<long long>; | ||
using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!std::convertible_to<CIter, Iter>); | ||
static_assert(!std::constructible_from<Iter, CIter>); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
283 changes: 283 additions & 0 deletions
283
...est/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/decrement.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// constexpr iterator& operator--() | ||
// requires ref-is-glvalue && bidirectional_range<Base> && | ||
// bidirectional-common<InnerBase> && bidirectional-common<PatternBase>; | ||
// constexpr iterator operator--(int) | ||
// requires ref-is-glvalue && bidirectional_range<Base> && | ||
// bidirectional-common<InnerBase> && bidirectional-common<PatternBase>; | ||
|
||
#include <ranges> | ||
|
||
#include <algorithm> | ||
#include <array> | ||
#include <cassert> | ||
#include <forward_list> | ||
#include <string> | ||
#include <string_view> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
|
||
template <class I> | ||
concept CanPreDecrement = requires(I& i) { | ||
{ --i } -> std::same_as<I&>; | ||
}; | ||
|
||
template <class I> | ||
concept CanPostDecrement = requires(I& i) { | ||
{ i-- } -> std::same_as<I>; | ||
}; | ||
|
||
template <class I> | ||
concept CanDecrement = CanPreDecrement<I> && CanPostDecrement<I>; | ||
|
||
constexpr bool test() { | ||
{ // `V` and `Pattern` are not empty. Test return type too. | ||
using V = std::ranges::owning_view<std::vector<std::string>>; | ||
using Pattern = std::ranges::single_view<char>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanDecrement<Iter>); | ||
static_assert(CanDecrement<CIter>); | ||
|
||
JWV jwv(V{{"01", "23", "45"}}, Pattern{'_'}); | ||
|
||
{ | ||
auto it = jwv.end(); | ||
std::same_as<Iter&> decltype(auto) it_ref = --it; | ||
assert(it_ref == it); | ||
assert(*it == '5'); | ||
std::same_as<Iter> decltype(auto) it_copy = it--; | ||
assert(--it_copy == it); | ||
--it; | ||
assert(*it == '_'); | ||
it--; | ||
assert(*it == '3'); | ||
--it; | ||
it--; | ||
assert(*it == '_'); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).end(); | ||
std::same_as<CIter&> decltype(auto) cit_ref = --cit; | ||
assert(cit_ref == cit); | ||
assert(*cit == '5'); | ||
std::same_as<CIter> decltype(auto) cit_copy = cit--; | ||
assert(--cit_copy == cit); | ||
--cit; | ||
assert(*cit == '_'); | ||
cit--; | ||
assert(*cit == '3'); | ||
--cit; | ||
cit--; | ||
assert(*cit == '_'); | ||
} | ||
|
||
assert(std::ranges::equal(std::views::reverse(std::move(jwv)), std::string_view{"54_32_10"})); | ||
} | ||
|
||
{ // `Pattern` is empty, `V` is not. | ||
using Inner = std::array<int, 1>; | ||
using V = std::ranges::owning_view<std::array<Inner, 3>>; | ||
using Pattern = std::ranges::owning_view<std::array<int, 0>>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{Inner{-9}, Inner{-99}, Inner{-999}}}, Pattern{}); | ||
|
||
{ | ||
auto it = jwv.end(); | ||
--it; | ||
assert(*it == -999); | ||
it--; | ||
assert(*it == -99); | ||
--it; | ||
assert(*it == -9); | ||
assert(it == jwv.begin()); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).end(); | ||
--cit; | ||
assert(*cit == -999); | ||
cit--; | ||
assert(*cit == -99); | ||
--cit; | ||
assert(*cit == -9); | ||
assert(cit == std::as_const(jwv).begin()); | ||
} | ||
} | ||
|
||
#if !defined(TEST_COMPILER_GCC) // GCC c++/101777 | ||
{ // `V` has empty subrange in the middle, `Pattern` is not empty. Try to go back and forth. | ||
using V = std::array<std::vector<int>, 3>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>; | ||
|
||
JWV jwv(V{{{5}, {}, {125}}}, Pattern{1}); | ||
|
||
{ | ||
auto it = jwv.end(); | ||
--it; | ||
assert(*it == 125); | ||
it--; | ||
assert(*it == 1); | ||
--it; | ||
assert(*it == 1); | ||
it--; | ||
assert(*it == 5); | ||
++it; | ||
assert(*it == 1); | ||
--it; | ||
assert(*it == 5); | ||
std::ranges::advance(it, 4); | ||
it--; | ||
assert(*it == 125); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).end(); | ||
--cit; | ||
assert(*cit == 125); | ||
cit--; | ||
assert(*cit == 1); | ||
--cit; | ||
assert(*cit == 1); | ||
cit--; | ||
assert(*cit == 5); | ||
++cit; | ||
assert(*cit == 1); | ||
--cit; | ||
assert(*cit == 5); | ||
std::ranges::advance(cit, 4); | ||
cit--; | ||
assert(*cit == 125); | ||
} | ||
} | ||
|
||
{ // Only first element of `V` is not empty. `Pattern` is empty. Try to go back and forth. | ||
using Inner = std::vector<int>; | ||
using V = std::ranges::owning_view<std::array<Inner, 3>>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{Inner{999}, {}, {}}}, Pattern{}); | ||
|
||
{ | ||
auto it = jwv.end(); | ||
--it; | ||
assert(*it == 999); | ||
++it; | ||
assert(it == jwv.end()); | ||
it--; | ||
assert(*it == 999); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).end(); | ||
--cit; | ||
assert(*cit == 999); | ||
++cit; | ||
assert(cit == std::as_const(jwv).end()); | ||
cit--; | ||
assert(*cit == 999); | ||
} | ||
} | ||
#endif // !defined(TEST_COMPILER_GCC) | ||
|
||
{ // `ref-is-glvalue` is false | ||
using V = RvalueVector<std::vector<int>>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
} | ||
|
||
{ // `Base` does not model bidirectional range | ||
using V = std::ranges::owning_view<std::forward_list<std::vector<int>>>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
static_assert(!CanPreDecrement<CIter>); | ||
static_assert(!CanPostDecrement<CIter>); | ||
} | ||
|
||
{ // InnerBase does not model bidirectional-common | ||
{ // InnerBase does not model bidirectional range | ||
using V = std::ranges::owning_view<std::vector<std::forward_list<int>>>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
static_assert(!CanPreDecrement<CIter>); | ||
static_assert(!CanPostDecrement<CIter>); | ||
} | ||
|
||
{ // InnerBase does not model common range | ||
using InnerBase = BasicVectorView<int, ViewProperties{.common = false}, bidirectional_iterator>; | ||
using V = std::ranges::owning_view<std::vector<InnerBase>>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
static_assert(!CanPreDecrement<CIter>); | ||
static_assert(!CanPostDecrement<CIter>); | ||
} | ||
} | ||
|
||
{ // PatternBase does not model bidirectional-common | ||
{ // PatternBase does not model bidirectional range | ||
using V = std::ranges::owning_view<std::vector<std::vector<int>>>; | ||
using Pattern = std::ranges::owning_view<std::forward_list<int>>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
static_assert(!CanPreDecrement<CIter>); | ||
static_assert(!CanPostDecrement<CIter>); | ||
} | ||
|
||
{ // PatternBase does not model common range | ||
using V = std::ranges::owning_view<std::vector<std::vector<int>>>; | ||
using Pattern = BasicVectorView<int, ViewProperties{.common = false}, bidirectional_iterator>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanPreDecrement<Iter>); | ||
static_assert(!CanPostDecrement<Iter>); | ||
static_assert(!CanPreDecrement<CIter>); | ||
static_assert(!CanPostDecrement<CIter>); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
144 changes: 144 additions & 0 deletions
144
...xx/test/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/deref.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// constexpr decltype(auto) operator*() const; | ||
|
||
#include <ranges> | ||
|
||
#include <array> | ||
#include <cassert> | ||
#include <string> | ||
#include <string_view> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
|
||
constexpr bool test() { | ||
{ // Result of `operator*` is (maybe const) lvalue reference | ||
using V = std::ranges::owning_view<std::vector<std::string>>; | ||
using Pattern = std::ranges::owning_view<std::string>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{"ab", "cd", "ef"}}, Pattern{"><"}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
std::same_as<char&> decltype(auto) v_ref = *std::as_const(it); | ||
assert(v_ref == 'a'); | ||
std::ranges::advance(it, 2); | ||
std::same_as<char&> decltype(auto) pattern_ref = *it; | ||
assert(pattern_ref == '>'); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
std::same_as<const char&> decltype(auto) cv_ref = *cit; | ||
assert(cv_ref == 'a'); | ||
std::ranges::advance(cit, 3); | ||
std::same_as<const char&> decltype(auto) cpattern_ref = *std::as_const(cit); | ||
assert(cpattern_ref == '<'); | ||
} | ||
} | ||
|
||
{ // Result of `operator*` is const lvalue reference | ||
using V = std::ranges::owning_view<std::vector<std::string_view>>; | ||
using Pattern = std::string_view; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{"123", "456", "789"}}, Pattern{"._."}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
std::same_as<const char&> decltype(auto) v_ref = *it; | ||
assert(v_ref == '1'); | ||
std::ranges::advance(it, 3); | ||
std::same_as<const char&> decltype(auto) pattern_ref = *std::as_const(it); | ||
assert(pattern_ref == '.'); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
std::same_as<const char&> decltype(auto) cv_ref = *std::as_const(cit); | ||
assert(cv_ref == '1'); | ||
std::ranges::advance(cit, 4); | ||
std::same_as<const char&> decltype(auto) cpattern_ref = *cit; | ||
assert(cpattern_ref == '_'); | ||
} | ||
} | ||
|
||
{ // Result of `operator*` is prvalue | ||
using V = std::vector<std::string_view>; | ||
using Pattern = RvalueVector<char>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
JWV jwv(V{"x^2", "y^2", "z^2"}, Pattern{{' ', '+', ' '}}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
std::same_as<char> decltype(auto) v_ref = *std::as_const(it); | ||
assert(v_ref == 'x'); | ||
std::ranges::advance(it, 3); | ||
std::same_as<char> decltype(auto) pattern_ref = *it; | ||
assert(pattern_ref == ' '); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
std::same_as<char> decltype(auto) cv_ref = *cit; | ||
assert(cv_ref == 'x'); | ||
std::ranges::advance(cit, 4); | ||
std::same_as<char> decltype(auto) cpattern_ref = *std::as_const(cit); | ||
assert(cpattern_ref == '+'); | ||
} | ||
} | ||
|
||
{ // Result of `operator*` is (maybe const) rvalue reference | ||
using Inner = std::ranges::as_rvalue_view<std::ranges::owning_view<std::string>>; | ||
using V = std::ranges::owning_view<std::vector<Inner>>; | ||
using Pattern = std::ranges::as_rvalue_view<std::ranges::owning_view<std::array<char, 2>>>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
std::vector<Inner> vec; | ||
vec.emplace_back(Inner{{"x*y"}}); | ||
vec.emplace_back(Inner{{"y*z"}}); | ||
vec.emplace_back(Inner{{"z*x"}}); | ||
JWV jwv(V(std::move(vec)), Pattern(std::array{',', ' '})); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
std::same_as<char&&> decltype(auto) v_ref = *it; | ||
assert(v_ref == 'x'); | ||
std::ranges::advance(it, 3); | ||
std::same_as<char&&> decltype(auto) pattern_ref = *std::as_const(it); | ||
assert(pattern_ref == ','); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
std::same_as<const char&&> decltype(auto) cv_ref = *std::as_const(cit); | ||
assert(cv_ref == 'x'); | ||
std::ranges::advance(cit, 4); | ||
std::same_as<const char&&> decltype(auto) cpattern_ref = *cit; | ||
assert(cpattern_ref == ' '); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
256 changes: 256 additions & 0 deletions
256
libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/eq.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// friend constexpr bool operator==(const iterator& x, const iterator& y) | ||
// requires ref-is-glvalue && forward_range<Base> && | ||
// equality_comparable<InnerIter>; | ||
|
||
#include <ranges> | ||
|
||
#include <array> | ||
#include <cassert> | ||
#include <utility> | ||
|
||
#include "../types.h" | ||
#include "test_comparisons.h" | ||
|
||
template <class I1, class I2 = I1> | ||
concept CanEq = requires(const I1& i1, const I2& i2) { | ||
{ i1 == i2 } -> std::same_as<bool>; | ||
{ i2 == i1 } -> std::same_as<bool>; | ||
{ i1 != i2 } -> std::same_as<bool>; | ||
{ i2 != i1 } -> std::same_as<bool>; | ||
}; | ||
|
||
constexpr bool test() { | ||
{ // `V` and `Pattern` are not empty. Test return types too. | ||
using V = std::array<std::array<int, 2>, 3>; | ||
using Pattern = std::array<long, 1>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanEq<Iter>); | ||
static_assert(CanEq<CIter>); | ||
static_assert(CanEq<Iter, CIter>); | ||
|
||
JWV jwv(V{{{9, 8}, {7, 6}, {5, 4}}}, Pattern{0L}); | ||
|
||
Iter it1 = jwv.begin(); | ||
assert(*it1 == 9); | ||
assert(testEquality(it1, it1, true)); | ||
|
||
Iter it2 = std::ranges::prev(jwv.end()); | ||
assert(*it2 == 4); | ||
assert(testEquality(it2, it2, true)); | ||
assert(testEquality(it1, it2, false)); | ||
|
||
CIter cit1 = std::as_const(jwv).begin(); | ||
assert(*cit1 == 9); | ||
assert(testEquality(cit1, cit1, true)); | ||
assert(testEquality(it1, cit1, true)); | ||
assert(testEquality(it2, cit1, false)); | ||
|
||
CIter cit2 = std::ranges::prev(std::as_const(jwv).end()); | ||
assert(*cit2 == 4); | ||
assert(testEquality(cit2, cit2, true)); | ||
assert(testEquality(cit1, cit2, false)); | ||
assert(testEquality(it1, cit2, false)); | ||
assert(testEquality(it2, cit2, true)); | ||
|
||
// `it1.inner_it_` and `it2.inner_it_` are equal, but `it1.outer_it_` and `it2.outer_it_` are not. | ||
std::ranges::advance(it1, 2); | ||
assert(*it1 == 0); | ||
std::ranges::advance(it2, -2); | ||
assert(*it2 == 0); | ||
assert(testEquality(it1, it2, false)); | ||
|
||
// `cit1.inner_it_` and `cit2.inner_it_` are equal, but `cit1.outer_it_` and `cit2.outer_it_` are not. | ||
std::ranges::advance(cit1, 2); | ||
assert(*cit1 == 0); | ||
assert(testEquality(it1, cit1, true)); | ||
std::ranges::advance(cit2, -2); | ||
assert(*cit2 == 0); | ||
assert(testEquality(it2, cit2, true)); | ||
assert(testEquality(cit1, cit2, false)); | ||
|
||
// `it1.inner_it_` and `it2.inner_it_` are equal, `it1.outer_it_` and `it2.outer_it_` are equal too. | ||
// `it1.inner_it_index()` and `it2.inner_it_index()` are equal to 1. | ||
++it1; | ||
assert(*it1 == 7); | ||
std::ranges::advance(it2, -2); | ||
assert(*it2 == 7); | ||
assert(testEquality(it1, it2, true)); | ||
|
||
// `cit1.inner_it_` and `cit2.inner_it_` are equal, `cit1.outer_it_` and `cit2.outer_it_` are equal too. | ||
// `cit1.inner_it_index()` and `cit2.inner_it_index()` are equal to 1. | ||
++cit1; | ||
assert(*cit1 == 7); | ||
assert(testEquality(it1, cit1, true)); | ||
std::ranges::advance(cit2, -2); | ||
assert(*cit2 == 7); | ||
assert(testEquality(it2, cit2, true)); | ||
assert(testEquality(cit1, cit2, true)); | ||
|
||
// `it1.inner_it_` and `it2.inner_it_` are equal, `it1.outer_it_` and `it2.outer_it_` are equal too. | ||
// `it1.inner_it_index()` and `it2.inner_it_index()` are equal to 0. | ||
--it1; | ||
assert(*it1 == 0); | ||
--it2; | ||
assert(*it2 == 0); | ||
assert(testEquality(it1, it2, true)); | ||
|
||
// `cit1.inner_it_` and `cit2.inner_it_` are equal, `cit1.outer_it_` and `cit2.outer_it_` are equal too. | ||
// `cit1.inner_it_index()` and `cit2.inner_it_index()` are equal to 0. | ||
--cit1; | ||
assert(*cit1 == 0); | ||
assert(testEquality(it1, cit1, true)); | ||
--cit2; | ||
assert(*cit2 == 0); | ||
assert(testEquality(it2, cit2, true)); | ||
assert(testEquality(cit2, cit2, true)); | ||
} | ||
|
||
{ // `InnerIter` models input iterator and equality comparable. `Pattern` is empty. | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, EqComparableInputIter>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanEq<Iter>); | ||
static_assert(CanEq<CIter>); | ||
static_assert(!CanEq<CIter, Iter>); | ||
|
||
JWV jwv(V{Inner{1, 2}, Inner{5, 6}, Inner{9, 0}}, Pattern{}); | ||
|
||
{ | ||
Iter it1 = jwv.begin(); | ||
assert(*it1 == 1); | ||
Iter it2 = std::ranges::next(jwv.begin(), 2); | ||
assert(*it2 == 5); | ||
assert(testEquality(it1, it2, false)); | ||
++it1; | ||
++it1; | ||
assert(testEquality(it1, it2, true)); | ||
++it1; | ||
assert(testEquality(it1, it2, false)); | ||
} | ||
|
||
{ | ||
CIter cit1 = std::as_const(jwv).begin(); | ||
assert(*cit1 == 1); | ||
CIter cit2 = std::ranges::next(std::as_const(jwv).begin(), 2); | ||
assert(*cit2 == 5); | ||
assert(testEquality(cit1, cit2, false)); | ||
++cit1; | ||
++cit1; | ||
assert(testEquality(cit1, cit2, true)); | ||
++cit1; | ||
assert(testEquality(cit1, cit2, false)); | ||
} | ||
} | ||
|
||
{ // `Pattern` is not empty. Some elements of `V` are. | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, EqComparableInputIter>; | ||
using V = BasicVectorView<Inner, ViewProperties{}, forward_iterator>; | ||
using Pattern = BasicVectorView<int, ViewProperties{.common = false}, forward_iterator>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanEq<Iter>); | ||
static_assert(CanEq<CIter>); | ||
static_assert(!CanEq<CIter, Iter>); | ||
|
||
JWV jwv(V{Inner{1}, Inner{}, Inner{27}}, Pattern{0}); | ||
|
||
{ | ||
Iter it1 = jwv.begin(); | ||
assert(*it1 == 1); | ||
++it1; | ||
assert(*it1 == 0); | ||
Iter it2 = jwv.begin(); | ||
assert(testEquality(it1, it2, false)); | ||
++it2; | ||
assert(testEquality(it1, it2, true)); | ||
|
||
++it2; | ||
assert(*it1 == *it2); | ||
assert(testEquality(it1, it2, false)); | ||
|
||
std::ranges::advance(it1, 2); | ||
++it2; | ||
assert(*it1 == *it2); | ||
assert(testEquality(it1, it2, true)); | ||
} | ||
|
||
{ | ||
CIter cit1 = std::as_const(jwv).begin(); | ||
assert(*cit1 == 1); | ||
++cit1; | ||
assert(*cit1 == 0); | ||
CIter cit2 = std::as_const(jwv).begin(); | ||
assert(testEquality(cit1, cit2, false)); | ||
++cit2; | ||
assert(testEquality(cit1, cit2, true)); | ||
|
||
++cit2; | ||
assert(*cit1 == *cit2); | ||
assert(testEquality(cit1, cit2, false)); | ||
|
||
std::ranges::advance(cit1, 2); | ||
++cit2; | ||
assert(*cit1 == *cit2); | ||
assert(testEquality(cit1, cit2, true)); | ||
} | ||
} | ||
|
||
{ // `ref-is-glvalue` is false | ||
using Inner = std::vector<int>; | ||
using V = RvalueVector<Inner>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
static_assert(!CanEq<Iter>); | ||
} | ||
|
||
{ // `Base` does not model forward range | ||
using Inner = std::vector<int>; | ||
using V = BasicVectorView<Inner, ViewProperties{}, DefaultCtorInputIter>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
static_assert(!CanEq<Iter>); | ||
} | ||
|
||
{ // `InnerIter` does not model equality comparable | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, cpp20_input_iterator>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(!CanEq<Iter>); | ||
static_assert(!CanEq<CIter>); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
320 changes: 320 additions & 0 deletions
320
...est/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/increment.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,320 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// constexpr iterator& operator++(); | ||
// constexpr void operator++(int); | ||
// constexpr iterator operator++(int) | ||
// requires ref-is-glvalue && forward_iterator<OuterIter> && | ||
// forward_iterator<InnerIter>; | ||
|
||
#include <ranges> | ||
|
||
#include <array> | ||
#include <cassert> | ||
#include <type_traits> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
|
||
template <class I> | ||
concept CanPreIncrement = requires(I& i) { ++i; }; | ||
|
||
template <class I> | ||
concept CanPostIncrement = requires(I& i) { i++; }; | ||
|
||
constexpr void test_pre_increment() { | ||
{ // `V` and `Pattern` are not empty. Test return type too. | ||
using V = std::array<std::array<int, 2>, 3>; | ||
using Pattern = std::array<int, 2>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanPreIncrement<Iter>); | ||
static_assert(!CanPreIncrement<const Iter>); | ||
static_assert(CanPreIncrement<CIter>); | ||
static_assert(!CanPreIncrement<const CIter>); | ||
|
||
JWV jwv(V{{{1, 1}, {2, 2}, {3, 3}}}, Pattern{0, 0}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
assert(*it == 1); | ||
std::same_as<Iter&> decltype(auto) it_ref = ++it; | ||
assert(it_ref == it); | ||
++it; | ||
assert(*it == 0); | ||
++it_ref; | ||
++it_ref; | ||
assert(*it_ref == 2); | ||
++it; | ||
++it_ref; | ||
assert(*it == 0); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
assert(*cit == 1); | ||
std::same_as<CIter&> decltype(auto) cit_ref = ++cit; | ||
assert(cit_ref == cit); | ||
++cit; | ||
assert(*cit == 0); | ||
++cit_ref; | ||
++cit_ref; | ||
assert(*cit_ref == 2); | ||
++cit; | ||
++cit_ref; | ||
assert(*cit == 0); | ||
} | ||
} | ||
|
||
#if !defined(TEST_COMPILER_GCC) // GCC c++/101777 | ||
|
||
{ // `Pattern` is empty, `V` is not. | ||
using V = std::array<std::vector<int>, 3>; | ||
using Pattern = std::vector<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
JWV jwv(V{{{-1}, {-2}, {-3}}}, Pattern{}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
assert(*it == -1); | ||
++it; | ||
assert(*it == -2); | ||
++it; | ||
assert(*it == -3); | ||
++it; | ||
assert(it == jwv.end()); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
assert(*cit == -1); | ||
++cit; | ||
assert(*cit == -2); | ||
++cit; | ||
assert(*cit == -3); | ||
++cit; | ||
assert(cit == std::as_const(jwv).end()); | ||
} | ||
} | ||
|
||
{ // `V` has empty subrange in the middle, `Pattern` is not empty. | ||
using V = std::array<std::vector<int>, 3>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>; | ||
|
||
JWV jwv(V{{{1}, {}, {3}}}, Pattern{0}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
assert(*it == 1); | ||
++it; | ||
assert(*it == 0); | ||
++it; | ||
assert(*it == 0); | ||
++it; | ||
assert(*it == 3); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
assert(*cit == 1); | ||
++cit; | ||
assert(*cit == 0); | ||
++cit; | ||
assert(*cit == 0); | ||
++cit; | ||
assert(*cit == 3); | ||
} | ||
} | ||
|
||
{ // Only first element of `V` is not empty. `Pattern` is empty. | ||
using V = std::array<std::vector<int>, 3>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>; | ||
|
||
JWV jwv(V{{{777}, {}, {}}}, Pattern{}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
assert(*it == 777); | ||
++it; | ||
assert(it == jwv.end()); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
assert(*cit == 777); | ||
++cit; | ||
assert(cit == std::as_const(jwv).end()); | ||
} | ||
} | ||
|
||
#endif // !defined(TEST_COMPILER_GCC) | ||
|
||
{ // Only last element of `V` is not empty. `Pattern` is empty. `V` models input range and `ref-is-glvalue` is false. | ||
using Inner = RvalueVector<std::string>; | ||
using V = BasicView<Inner, ViewProperties{}, DefaultCtorInputIter>; | ||
using Pattern = std::ranges::empty_view<char>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{}, {}, {'a'}}, Pattern{}); | ||
|
||
auto it = jwv.begin(); | ||
assert(*it == 'a'); | ||
++it; | ||
assert(it == jwv.end()); | ||
} | ||
|
||
{ // Only first element of `V` is not empty. `Pattern` is not empty. | ||
// `V` models input range and `ref-is-glvalue` is false. | ||
using Inner = RvalueVector<std::string>; | ||
using V = BasicView<Inner, ViewProperties{}, DefaultCtorInputIter>; | ||
using Pattern = std::ranges::single_view<char>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{{'b'}, {}, {}}, Pattern{'.'}); | ||
|
||
auto it = jwv.begin(); | ||
assert(*it == 'b'); | ||
++it; | ||
assert(*it == '.'); | ||
++it; | ||
assert(*it == '.'); | ||
++it; | ||
assert(it == jwv.end()); | ||
} | ||
} | ||
|
||
constexpr void test_post_increment() { | ||
{ // `V` and `Pattern` are not empty. Test return type too. | ||
using V = std::array<std::array<int, 3>, 2>; | ||
using Pattern = std::array<int, 1>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
using Iter = std::ranges::iterator_t<JWV>; | ||
using CIter = std::ranges::iterator_t<const JWV>; | ||
static_assert(CanPostIncrement<Iter>); | ||
static_assert(!CanPostIncrement<const Iter>); | ||
static_assert(CanPostIncrement<CIter>); | ||
static_assert(!CanPostIncrement<const CIter>); | ||
|
||
JWV jwv(V{{{6, 5, 4}, {3, 2, 1}}}, Pattern{-5}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
assert(*it == 6); | ||
std::same_as<Iter> decltype(auto) it_copy = it++; | ||
assert(++it_copy == it); | ||
it++; | ||
it++; | ||
assert(*it == -5); | ||
it_copy++; | ||
it_copy++; | ||
assert(*it_copy == -5); | ||
it++; | ||
it_copy++; | ||
assert(*it == 3); | ||
assert(*it_copy == 3); | ||
} | ||
|
||
{ | ||
auto cit = std::as_const(jwv).begin(); | ||
assert(*cit == 6); | ||
std::same_as<CIter> decltype(auto) cit_copy = cit++; | ||
assert(++cit_copy == cit); | ||
cit++; | ||
cit++; | ||
assert(*cit == -5); | ||
cit_copy++; | ||
cit_copy++; | ||
assert(*cit_copy == -5); | ||
cit++; | ||
cit_copy++; | ||
assert(*cit == 3); | ||
assert(*cit_copy == 3); | ||
} | ||
} | ||
|
||
{ // `Pattern` is empty, `V` is not. `ref-is-glvalue` is false. | ||
using Inner = std::vector<int>; | ||
using V = RvalueVector<Inner>; | ||
using Pattern = std::ranges::empty_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
JWV jwv(V{Inner{-3}, Inner{-2}, Inner{-1}}, Pattern{}); | ||
|
||
auto it = jwv.begin(); | ||
assert(*it == -3); | ||
it++; | ||
assert(*it == -2); | ||
it++; | ||
assert(*it == -1); | ||
it++; | ||
assert(it == jwv.end()); | ||
static_assert(std::is_void_v<decltype(it++)>); | ||
} | ||
|
||
{ // `V` has empty subrange in the middle, `Pattern` is not empty. OuterIter does not model forward iterator. | ||
using Inner = std::vector<int>; | ||
using V = BasicVectorView<Inner, ViewProperties{.common = false}, cpp20_input_iterator>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
|
||
JWV jwv(V{Inner{7}, {}, Inner{9}}, Pattern{8}); | ||
|
||
auto it = jwv.begin(); | ||
assert(*it == 7); | ||
it++; | ||
assert(*it == 8); | ||
it++; | ||
assert(*it == 8); | ||
it++; | ||
assert(*it == 9); | ||
it++; | ||
assert(it == jwv.end()); | ||
static_assert(std::is_void_v<decltype(it++)>); | ||
} | ||
|
||
#if !defined(TEST_COMPILER_GCC) // GCC c++/101777 | ||
{ // Only first element of `V` is not empty. `Pattern` is empty. InnerIter does not model forward iterator. | ||
using Inner = BasicVectorView<char32_t, ViewProperties{.common = false}, cpp17_input_iterator>; | ||
using V = std::array<Inner, 3>; | ||
using Pattern = std::ranges::empty_view<char32_t>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>; | ||
|
||
JWV jwv(V{Inner{U'?'}, Inner{}, Inner{}}, Pattern{}); | ||
|
||
auto it = jwv.begin(); | ||
assert(*it == U'?'); | ||
it++; | ||
assert(it == jwv.end()); | ||
static_assert(std::is_void_v<decltype(it++)>); | ||
} | ||
#endif // !defined(TEST_COMPILER_GCC) | ||
} | ||
|
||
constexpr bool test() { | ||
test_pre_increment(); | ||
test_post_increment(); | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
340 changes: 340 additions & 0 deletions
340
...est/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/iter_move.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,340 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// friend constexpr decltype(auto) iter_move(const iterator& x) { | ||
// using rvalue_reference = common_reference_t< | ||
// iter_rvalue_reference_t<InnerIter>, | ||
// iter_rvalue_reference_t<PatternIter>>; | ||
// return visit<rvalue_reference>(ranges::iter_move, x.inner_it_); | ||
// } | ||
|
||
#include <ranges> | ||
|
||
#include <algorithm> | ||
#include <array> | ||
#include <cassert> | ||
#include <type_traits> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
|
||
class MoveOnlyInt { | ||
public: | ||
enum Status { constructed, move_constructed, moved_from_this }; | ||
|
||
MoveOnlyInt() = default; | ||
constexpr MoveOnlyInt(int val) : val_(val) {} | ||
|
||
constexpr MoveOnlyInt(MoveOnlyInt&& other) noexcept : val_(other.val_), status_(move_constructed) { | ||
other.val_ = -1; | ||
other.status_ = moved_from_this; | ||
} | ||
|
||
constexpr MoveOnlyInt(const MoveOnlyInt&& other) noexcept : val_(other.val_), status_(move_constructed) { | ||
other.val_ = -1; | ||
other.status_ = moved_from_this; | ||
} | ||
|
||
MoveOnlyInt(const MoveOnlyInt&) { assert(false); } // Should never be called in this test. | ||
|
||
MoveOnlyInt& operator=(MoveOnlyInt&&) { // Should never be called in this test. | ||
assert(false); | ||
return *this; | ||
} | ||
|
||
constexpr Status get_status() const { return status_; } | ||
|
||
friend constexpr bool operator==(const MoveOnlyInt& left, int right) { return left.val_ == right; } | ||
friend constexpr bool operator==(const MoveOnlyInt& left, const MoveOnlyInt& right) { | ||
return left.val_ == right.val_; | ||
} | ||
|
||
private: | ||
mutable int val_ = -1; | ||
mutable Status status_ = constructed; | ||
}; | ||
|
||
static_assert(std::movable<MoveOnlyInt>); | ||
|
||
template <class T> | ||
class ProxyRvalue { | ||
T val_; | ||
|
||
public: | ||
constexpr ProxyRvalue(T val) : val_(std::move(val)) {} | ||
|
||
ProxyRvalue(ProxyRvalue&&) = default; | ||
ProxyRvalue& operator=(ProxyRvalue&&) = default; | ||
|
||
constexpr explicit operator T&&() noexcept { return std::move(val_); } | ||
}; | ||
|
||
static_assert(std::common_reference_with<ProxyRvalue<int>, int>); | ||
static_assert(std::common_reference_with<ProxyRvalue<MoveOnlyInt>, MoveOnlyInt>); | ||
|
||
template <std::bidirectional_iterator It> | ||
class ProxyOnIterMoveIter { | ||
It it_ = It(); | ||
|
||
public: | ||
using value_type = std::iter_value_t<It>; | ||
using difference_type = std::iter_difference_t<It>; | ||
|
||
ProxyOnIterMoveIter() = default; | ||
constexpr ProxyOnIterMoveIter(It it) : it_(std::move(it)) {} | ||
|
||
constexpr decltype(auto) operator*() const { return *it_; } | ||
|
||
constexpr ProxyOnIterMoveIter& operator++() { | ||
++it_; | ||
return *this; | ||
} | ||
|
||
constexpr ProxyOnIterMoveIter operator++(int) { | ||
ProxyOnIterMoveIter copy = *this; | ||
++it_; | ||
return copy; | ||
} | ||
|
||
constexpr ProxyOnIterMoveIter& operator--() { | ||
--it_; | ||
return *this; | ||
} | ||
|
||
constexpr ProxyOnIterMoveIter operator--(int) { | ||
ProxyOnIterMoveIter copy = *this; | ||
--it_; | ||
return copy; | ||
} | ||
|
||
friend bool operator==(const ProxyOnIterMoveIter&, const ProxyOnIterMoveIter&) = default; | ||
|
||
friend constexpr ProxyRvalue<value_type> iter_move(const ProxyOnIterMoveIter iter) { | ||
return ProxyRvalue<value_type>{std::ranges::iter_move(iter.it_)}; | ||
} | ||
}; | ||
|
||
template <class It> | ||
ProxyOnIterMoveIter(It) -> ProxyOnIterMoveIter<It>; | ||
|
||
static_assert(std::bidirectional_iterator<ProxyOnIterMoveIter<int*>>); | ||
|
||
constexpr bool test() { | ||
{ // Test `iter_move` when result is true rvalue reference. Test return types. | ||
using V = std::array<std::array<char, 1>, 2>; | ||
using Pattern = std::array<char, 1>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
JWV jwv(V{{{'0'}, {'1'}}}, Pattern{','}); | ||
|
||
{ | ||
auto it = jwv.begin(); | ||
std::same_as<char&&> decltype(auto) v_rref1 = iter_move(it); | ||
std::same_as<char&&> decltype(auto) v_rref2 = iter_move(std::as_const(it)); | ||
std::same_as<char&&> decltype(auto) v_rref3 = std::ranges::iter_move(it); | ||
std::same_as<char&&> decltype(auto) v_rref4 = std::ranges::iter_move(std::as_const(it)); | ||
assert(std::ranges::equal(std::array{v_rref1, v_rref2, v_rref3, v_rref4}, std::views::repeat('0', 4))); | ||
|
||
++it; // `it` points to element of `Pattern` from here | ||
std::same_as<char&&> decltype(auto) pattern_rref1 = iter_move(it); | ||
std::same_as<char&&> decltype(auto) pattern_rref2 = iter_move(std::as_const(it)); | ||
std::same_as<char&&> decltype(auto) pattern_rref3 = std::ranges::iter_move(it); | ||
std::same_as<char&&> decltype(auto) pattern_rref4 = std::ranges::iter_move(std::as_const(it)); | ||
assert(std::ranges::equal( | ||
std::array{pattern_rref1, pattern_rref2, pattern_rref3, pattern_rref4}, std::views::repeat(',', 4))); | ||
} | ||
|
||
{ | ||
auto cit = std::prev(std::as_const(jwv).end()); | ||
std::same_as<const char&&> decltype(auto) cv_rref1 = iter_move(cit); | ||
std::same_as<const char&&> decltype(auto) cv_rref2 = iter_move(std::as_const(cit)); | ||
std::same_as<const char&&> decltype(auto) cv_rref3 = std::ranges::iter_move(cit); | ||
std::same_as<const char&&> decltype(auto) cv_rref4 = std::ranges::iter_move(std::as_const(cit)); | ||
assert(std::ranges::equal(std::array{cv_rref1, cv_rref2, cv_rref3, cv_rref4}, std::views::repeat('1', 4))); | ||
|
||
cit--; // `cit` points to element of `Pattern` from here | ||
std::same_as<const char&&> decltype(auto) cpattern_rref1 = iter_move(cit); | ||
std::same_as<const char&&> decltype(auto) cpattern_rref2 = iter_move(std::as_const(cit)); | ||
std::same_as<const char&&> decltype(auto) cpattern_rref3 = std::ranges::iter_move(cit); | ||
std::same_as<const char&&> decltype(auto) cpattern_rref4 = std::ranges::iter_move(std::as_const(cit)); | ||
assert(std::ranges::equal( | ||
std::array{cpattern_rref1, cpattern_rref2, cpattern_rref3, cpattern_rref4}, std::views::repeat(',', 4))); | ||
} | ||
} | ||
|
||
{ // Test `iter_move` when result is true rvalue reference. Test moving. | ||
using Inner = std::vector<MoveOnlyInt>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::vector<MoveOnlyInt>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
V v; | ||
v.reserve(2); | ||
v.emplace_back(std::ranges::to<Inner>(std::views::iota(0, 4))); | ||
v.emplace_back(std::ranges::to<Inner>(std::views::iota(12, 16))); | ||
JWV jwv(std::move(v), std::ranges::to<Pattern>(std::views::iota(4, 12))); | ||
assert(std::ranges::all_of(jwv, [](const MoveOnlyInt& i) { return i.get_status() == MoveOnlyInt::constructed; })); | ||
|
||
{ | ||
using enum MoveOnlyInt::Status; | ||
std::vector<MoveOnlyInt> values; | ||
values.reserve(8); | ||
|
||
auto it = jwv.begin(); | ||
values.emplace_back(iter_move(it)); | ||
++it; | ||
values.emplace_back(iter_move(std::as_const(it))); | ||
it++; | ||
values.emplace_back(std::ranges::iter_move(it)); | ||
++it; | ||
values.emplace_back(std::ranges::iter_move(std::as_const(it))); | ||
it++; // `it` points to element of `Pattern` from here | ||
values.emplace_back(iter_move(it)); | ||
++it; | ||
values.emplace_back(iter_move(std::as_const(it))); | ||
it++; | ||
values.emplace_back(std::ranges::iter_move(it)); | ||
++it; | ||
values.emplace_back(std::ranges::iter_move(std::as_const(it))); | ||
|
||
assert(std::ranges::equal(values, std::views::iota(0, 8))); | ||
assert(std::ranges::all_of(values, [](const MoveOnlyInt& i) { return i.get_status() == move_constructed; })); | ||
} | ||
|
||
{ | ||
using enum MoveOnlyInt::Status; | ||
std::vector<MoveOnlyInt> values; | ||
values.reserve(8); | ||
|
||
auto cit = std::prev(std::as_const(jwv).end()); | ||
values.emplace_back(iter_move(cit)); | ||
cit--; | ||
values.emplace_back(iter_move(std::as_const(cit))); | ||
--cit; | ||
values.emplace_back(std::ranges::iter_move(cit)); | ||
cit--; | ||
values.emplace_back(std::ranges::iter_move(std::as_const(cit))); | ||
--cit; // `it` points to element of `Pattern` from here | ||
values.emplace_back(iter_move(cit)); | ||
cit--; | ||
values.emplace_back(iter_move(std::as_const(cit))); | ||
--cit; | ||
values.emplace_back(std::ranges::iter_move(cit)); | ||
cit--; | ||
values.emplace_back(std::ranges::iter_move(std::as_const(cit))); | ||
|
||
assert(std::ranges::equal(std::views::reverse(values), std::views::iota(8, 16))); | ||
assert(std::ranges::all_of(values, [](const MoveOnlyInt& i) { return i.get_status() == move_constructed; })); | ||
} | ||
|
||
assert( | ||
std::ranges::all_of(jwv, [](const MoveOnlyInt& i) { return i.get_status() == MoveOnlyInt::moved_from_this; })); | ||
} | ||
|
||
{ // Test `iter_move` when result is proxy rvalue reference. Test return types and moving. | ||
using Inner = std::vector<MoveOnlyInt>; | ||
using V = std::vector<Inner>; | ||
using Pattern = BasicVectorView<MoveOnlyInt, ViewProperties{}, ProxyOnIterMoveIter>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
|
||
using RRef = ProxyRvalue<MoveOnlyInt>; | ||
static_assert(std::same_as<RRef, std::ranges::range_rvalue_reference_t<JWV>>); | ||
|
||
V v; | ||
v.reserve(2); | ||
v.emplace_back(std::ranges::to<Inner>(std::views::iota(0, 4))); | ||
v.emplace_back(std::ranges::to<Inner>(std::views::iota(12, 16))); | ||
JWV jwv(std::move(v), Pattern{std::ranges::to<std::vector<MoveOnlyInt>>(std::views::iota(4, 12))}); | ||
assert(std::ranges::all_of(jwv, [](const MoveOnlyInt& i) { return i.get_status() == MoveOnlyInt::constructed; })); | ||
|
||
{ | ||
using enum MoveOnlyInt::Status; | ||
std::vector<MoveOnlyInt> values; | ||
values.reserve(8); | ||
|
||
auto it = jwv.begin(); | ||
std::same_as<RRef> decltype(auto) rref1 = iter_move(it); | ||
values.emplace_back(std::move(rref1)); | ||
++it; | ||
std::same_as<RRef> decltype(auto) rref2 = iter_move(std::as_const(it)); | ||
values.emplace_back(rref2); | ||
it++; | ||
std::same_as<RRef> decltype(auto) rref3 = std::ranges::iter_move(it); | ||
values.emplace_back(rref3); | ||
++it; | ||
std::same_as<RRef> decltype(auto) rref4 = std::ranges::iter_move(std::as_const(it)); | ||
values.emplace_back(rref4); | ||
it++; // `it` points to element of `Pattern` from here | ||
std::same_as<RRef> decltype(auto) rref5 = iter_move(it); | ||
values.emplace_back(rref5); | ||
++it; | ||
std::same_as<RRef> decltype(auto) rref6 = iter_move(std::as_const(it)); | ||
values.emplace_back(rref6); | ||
it++; | ||
std::same_as<RRef> decltype(auto) rref7 = std::ranges::iter_move(it); | ||
values.emplace_back(rref7); | ||
++it; | ||
std::same_as<RRef> decltype(auto) rref8 = std::ranges::iter_move(std::as_const(it)); | ||
values.emplace_back(rref8); | ||
|
||
assert(std::ranges::equal(values, std::views::iota(0, 8))); | ||
assert(std::ranges::all_of(values, [](const MoveOnlyInt& i) { return i.get_status() == move_constructed; })); | ||
} | ||
|
||
{ | ||
using enum MoveOnlyInt::Status; | ||
std::vector<MoveOnlyInt> values; | ||
values.reserve(8); | ||
|
||
auto cit = std::prev(std::as_const(jwv).end()); | ||
std::same_as<RRef> decltype(auto) rref1 = iter_move(cit); | ||
values.emplace_back(rref1); | ||
cit--; | ||
std::same_as<RRef> decltype(auto) rref2 = iter_move(std::as_const(cit)); | ||
values.emplace_back(rref2); | ||
--cit; | ||
std::same_as<RRef> decltype(auto) rref3 = std::ranges::iter_move(cit); | ||
values.emplace_back(rref3); | ||
cit--; | ||
std::same_as<RRef> decltype(auto) rref4 = std::ranges::iter_move(std::as_const(cit)); | ||
values.emplace_back(rref4); | ||
--cit; // `it` points to element of `Pattern` from here | ||
std::same_as<RRef> decltype(auto) rref5 = iter_move(cit); | ||
values.emplace_back(rref5); | ||
cit--; | ||
std::same_as<RRef> decltype(auto) rref6 = iter_move(std::as_const(cit)); | ||
values.emplace_back(rref6); | ||
--cit; | ||
std::same_as<RRef> decltype(auto) rref7 = std::ranges::iter_move(cit); | ||
values.emplace_back(rref7); | ||
cit--; | ||
std::same_as<RRef> decltype(auto) rref8 = std::ranges::iter_move(std::as_const(cit)); | ||
values.emplace_back(rref8); | ||
|
||
assert(std::ranges::equal(std::views::reverse(values), std::views::iota(8, 16))); | ||
assert(std::ranges::all_of(values, [](const MoveOnlyInt& i) { return i.get_status() == move_constructed; })); | ||
} | ||
|
||
assert( | ||
std::ranges::all_of(jwv, [](const MoveOnlyInt& i) { return i.get_status() == MoveOnlyInt::moved_from_this; })); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
81 changes: 81 additions & 0 deletions
81
...est/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/iter_swap.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// friend constexpr void iter_swap(const iterator& x, const iterator& y) | ||
// requires indirectly_swappable<InnerIter, PatternIter> { | ||
// visit(ranges::iter_swap, x.inner_it_, y.inner_it_); | ||
// } | ||
|
||
#include <ranges> | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <span> | ||
#include <string> | ||
#include <string_view> | ||
#include <type_traits> | ||
#include <utility> | ||
#include <vector> | ||
|
||
template <class I> | ||
concept CanIterSwap = requires(I i) { iter_swap(i); }; | ||
|
||
constexpr bool test() { | ||
{ // Test common usage | ||
using V = std::vector<std::string>; | ||
using Pattern = std::string; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; | ||
using namespace std::string_view_literals; | ||
|
||
JWV jwv(V{"std", "ranges", "views", "join_with_view"}, Pattern{":: "}); | ||
assert(std::ranges::equal(jwv, "std:: ranges:: views:: join_with_view"sv)); | ||
|
||
auto it = jwv.begin(); | ||
iter_swap(it, std::ranges::next(it, 2)); // Swap elements of the same inner range. | ||
assert(std::ranges::equal(jwv, "dts:: ranges:: views:: join_with_view"sv)); | ||
|
||
std::ranges::advance(it, 3); | ||
iter_swap(std::as_const(it), std::ranges::next(it, 2)); // Swap elements of the pattern. | ||
assert(std::ranges::equal(jwv, "dts ::ranges ::views ::join_with_view"sv)); | ||
|
||
std::ranges::advance(it, 3); | ||
const auto it2 = jwv.begin(); | ||
iter_swap(std::as_const(it), it2); // Swap elements of different inner ranges. | ||
assert(std::ranges::equal(jwv, "rts ::danges ::views ::join_with_view"sv)); | ||
|
||
std::ranges::advance(it, 6); | ||
iter_swap(std::as_const(it), it2); // Swap element from inner range with element from the pattern. | ||
assert(std::ranges::equal(jwv, " tsr::dangesr::viewsr::join_with_view"sv)); | ||
|
||
static_assert(std::is_void_v<decltype(iter_swap(it, it))>); | ||
static_assert(std::is_void_v<decltype(iter_swap(it2, it2))>); | ||
static_assert(!CanIterSwap<std::ranges::iterator_t<const JWV>>); | ||
static_assert(!CanIterSwap<const std::ranges::iterator_t<const JWV>>); | ||
} | ||
|
||
{ // InnerIter and PatternIter don't model indirectly swappable | ||
using JWV = std::ranges::join_with_view<std::span<std::string>, std::string_view>; | ||
static_assert(!CanIterSwap<std::ranges::iterator_t<JWV>>); | ||
static_assert(!CanIterSwap<const std::ranges::iterator_t<JWV>>); | ||
static_assert(!CanIterSwap<std::ranges::iterator_t<const JWV>>); | ||
static_assert(!CanIterSwap<const std::ranges::iterator_t<const JWV>>); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
456 changes: 456 additions & 0 deletions
456
...std/ranges/range.adaptors/range.join.with/range.join.with.iterator/types.compile.pass.cpp
Large diffs are not rendered by default.
Oops, something went wrong.
359 changes: 359 additions & 0 deletions
359
.../test/std/ranges/range.adaptors/range.join.with/range.join.with.overview/adaptor.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,359 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// std::views::join_with_view | ||
|
||
#include <ranges> | ||
|
||
#include <span> | ||
#include <string_view> | ||
#include <utility> | ||
|
||
#include "test_iterators.h" | ||
|
||
template <class View, class T> | ||
concept CanBePiped = requires(View&& view, T&& t) { | ||
{ std::forward<View>(view) | std::forward<T>(t) }; | ||
}; | ||
|
||
struct Range : std::ranges::view_base { | ||
using Iterator = forward_iterator<std::string_view*>; | ||
using Sentinel = sentinel_wrapper<Iterator>; | ||
constexpr explicit Range(std::string_view* b, std::string_view* e) : begin_(b), end_(e) {} | ||
constexpr Iterator begin() const { return Iterator(begin_); } | ||
constexpr Sentinel end() const { return Sentinel(Iterator(end_)); } | ||
|
||
private: | ||
std::string_view* begin_; | ||
std::string_view* end_; | ||
}; | ||
|
||
struct Pattern : std::ranges::view_base { | ||
using Iterator = forward_iterator<const char*>; | ||
using Sentinel = sentinel_wrapper<Iterator>; | ||
static constexpr std::string_view pat{", "}; | ||
|
||
constexpr Pattern() = default; | ||
constexpr Iterator begin() const { return Iterator(pat.data()); } | ||
constexpr Sentinel end() const { return Sentinel(Iterator(pat.data() + pat.size())); } | ||
}; | ||
|
||
struct NonCopyablePattern : Pattern { | ||
NonCopyablePattern(const NonCopyablePattern&) = delete; | ||
}; | ||
|
||
template <typename View> | ||
constexpr void compareViews(View v, std::string_view list) { | ||
auto b1 = v.begin(); | ||
auto e1 = v.end(); | ||
auto b2 = list.begin(); | ||
auto e2 = list.end(); | ||
for (; b1 != e1 && b2 != e2; ++b1, ++b2) { | ||
assert(*b1 == *b2); | ||
} | ||
assert(b1 == e1); | ||
assert(b2 == e2); | ||
} | ||
|
||
constexpr int absoluteValue(int x) { return x < 0 ? -x : x; } | ||
|
||
template <class T> | ||
constexpr const T&& asConstRvalue(T&& t) { | ||
return static_cast<const T&&>(t); | ||
} | ||
|
||
constexpr void test_adaptor_with_pattern(std::span<std::string_view> buff) { | ||
// Test `views::join_with(pattern)(v)` | ||
{ | ||
using Result = std::ranges::join_with_view<Range, Pattern>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
Pattern pattern; | ||
|
||
{ | ||
// 'views::join_with(pattern)' - && | ||
std::same_as<Result> decltype(auto) result = std::views::join_with(pattern)(range); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - const&& | ||
std::same_as<Result> decltype(auto) result = asConstRvalue(std::views::join_with(pattern))(range); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - & | ||
auto partial = std::views::join_with(pattern); | ||
std::same_as<Result> decltype(auto) result = partial(range); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - const& | ||
auto const partial = std::views::join_with(pattern); | ||
std::same_as<Result> decltype(auto) result = partial(range); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
} | ||
|
||
// Test `v | views::join_with(pattern)` | ||
{ | ||
using Result = std::ranges::join_with_view<Range, Pattern>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
Pattern pattern; | ||
|
||
{ | ||
// 'views::join_with(pattern)' - && | ||
std::same_as<Result> decltype(auto) result = range | std::views::join_with(pattern); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - const&& | ||
std::same_as<Result> decltype(auto) result = range | asConstRvalue(std::views::join_with(pattern)); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - & | ||
auto partial = std::views::join_with(pattern); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with(pattern)' - const& | ||
auto const partial = std::views::join_with(pattern); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
} | ||
|
||
// Test `views::join_with(v, pattern)` range adaptor object | ||
{ | ||
using Result = std::ranges::join_with_view<Range, Pattern>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
Pattern pattern; | ||
|
||
{ | ||
// 'views::join_with' - && | ||
auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pattern); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with' - const&& | ||
const auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pattern); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with' - & | ||
auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = range_adaptor(range, pattern); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
{ | ||
// 'views::join_with' - const& | ||
const auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = range_adaptor(range, pattern); | ||
compareViews(result, "abcd, ef, ghij, kl"); | ||
} | ||
} | ||
|
||
// Test `adaptor | views::join_with(pattern)` | ||
{ | ||
auto pred = [](std::string_view s) { return s.size() >= 3; }; | ||
using Result = std::ranges::join_with_view<std::ranges::filter_view<Range, decltype(pred)>, Pattern>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
Pattern pattern; | ||
|
||
{ | ||
std::same_as<Result> decltype(auto) result = range | std::views::filter(pred) | std::views::join_with(pattern); | ||
compareViews(result, "abcd, ghij"); | ||
} | ||
{ | ||
const auto partial = std::views::filter(pred) | std::views::join_with(pattern); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd, ghij"); | ||
} | ||
} | ||
} | ||
|
||
constexpr void test_adaptor_with_single_element(std::span<std::string_view> buff) { | ||
// Test `views::join_with(element)(v)` | ||
{ | ||
using Result = std::ranges::join_with_view<Range, std::ranges::single_view<char>>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
const char element = '.'; | ||
|
||
{ | ||
// 'views::join_with(element)' - && | ||
std::same_as<Result> decltype(auto) result = std::views::join_with(element)(range); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - const&& | ||
std::same_as<Result> decltype(auto) result = asConstRvalue(std::views::join_with(element))(range); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - & | ||
auto partial = std::views::join_with(element); | ||
std::same_as<Result> decltype(auto) result = partial(range); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - const& | ||
const auto partial = std::views::join_with(element); | ||
std::same_as<Result> decltype(auto) result = partial(range); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
} | ||
|
||
// Test `v | views::join_with(element)` | ||
{ | ||
using Result = std::ranges::join_with_view<Range, std::ranges::single_view<char>>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
const char element = '.'; | ||
|
||
{ | ||
// 'views::join_with(element)' - && | ||
std::same_as<Result> decltype(auto) result = range | std::views::join_with(element); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - const&& | ||
std::same_as<Result> decltype(auto) result = range | asConstRvalue(std::views::join_with(element)); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - & | ||
auto partial = std::views::join_with(element); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with(element)' - const& | ||
const auto partial = std::views::join_with(element); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
} | ||
|
||
// Test `views::join_with(v, element)` range adaptor object | ||
{ | ||
using Result = std::ranges::join_with_view<Range, std::ranges::single_view<char>>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
const char element = '.'; | ||
|
||
{ | ||
// 'views::join_with' - && | ||
auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, element); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with' - const&& | ||
const auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, element); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with' - & | ||
auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = range_adaptor(range, element); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
{ | ||
// 'views::join_with' - const& | ||
const auto range_adaptor = std::views::join_with; | ||
std::same_as<Result> decltype(auto) result = range_adaptor(range, element); | ||
compareViews(result, "abcd.ef.ghij.kl"); | ||
} | ||
} | ||
|
||
// Test `adaptor | views::join_with(element)` | ||
{ | ||
auto pred = [](std::string_view s) { return s.size() >= 3; }; | ||
using Result = | ||
std::ranges::join_with_view<std::ranges::filter_view<Range, decltype(pred)>, std::ranges::single_view<char>>; | ||
const Range range(buff.data(), buff.data() + buff.size()); | ||
const char element = '.'; | ||
|
||
{ | ||
std::same_as<Result> decltype(auto) result = range | std::views::filter(pred) | std::views::join_with(element); | ||
compareViews(result, "abcd.ghij"); | ||
} | ||
{ | ||
const auto partial = std::views::filter(pred) | std::views::join_with(element); | ||
std::same_as<Result> decltype(auto) result = range | partial; | ||
compareViews(result, "abcd.ghij"); | ||
} | ||
} | ||
} | ||
|
||
constexpr bool test() { | ||
std::string_view buff[] = {"abcd", "ef", "ghij", "kl"}; | ||
|
||
// Test range adaptor object | ||
{ | ||
using RangeAdaptorObject = decltype(std::views::join_with); | ||
static_assert(std::is_const_v<RangeAdaptorObject>); | ||
|
||
// The type of a customization point object, ignoring cv-qualifiers, shall model semiregular | ||
static_assert(std::semiregular<std::remove_const<RangeAdaptorObject>>); | ||
} | ||
|
||
test_adaptor_with_pattern(buff); | ||
test_adaptor_with_single_element(buff); | ||
|
||
// Test that one can call std::views::join_with with arbitrary stuff, as long as we | ||
// don't try to actually complete the call by passing it a range. | ||
// | ||
// That makes no sense and we can't do anything with the result, but it's valid. | ||
{ | ||
long array[3] = {1, 2, 3}; | ||
[[maybe_unused]] auto partial = std::views::join_with(std::move(array)); | ||
} | ||
|
||
// Test SFINAE friendliness | ||
{ | ||
struct NotAView {}; | ||
|
||
static_assert(!CanBePiped<Range, decltype(std::views::join_with)>); | ||
static_assert(CanBePiped<Range, decltype(std::views::join_with(Pattern{}))>); | ||
static_assert(CanBePiped<Range, decltype(std::views::join_with('.'))>); | ||
static_assert(!CanBePiped<NotAView, decltype(std::views::join_with(Pattern{}))>); | ||
static_assert(!CanBePiped<NotAView, decltype(std::views::join_with('.'))>); | ||
static_assert(!CanBePiped<std::initializer_list<char>, decltype(std::views::join_with(Pattern{}))>); | ||
static_assert(!CanBePiped<std::initializer_list<char>, decltype(std::views::join_with('.'))>); | ||
static_assert(!CanBePiped<Range, decltype(std::views::join_with(NotAView{}))>); | ||
|
||
static_assert(!std::is_invocable_v<decltype(std::views::join_with)>); | ||
static_assert(!std::is_invocable_v<decltype(std::views::join_with), Pattern, Range>); | ||
static_assert(!std::is_invocable_v<decltype(std::views::join_with), char, Range>); | ||
static_assert(std::is_invocable_v<decltype(std::views::join_with), Range, Pattern>); | ||
static_assert(std::is_invocable_v<decltype(std::views::join_with), Range, char>); | ||
static_assert(!std::is_invocable_v<decltype(std::views::join_with), Range, Pattern, Pattern>); | ||
static_assert(!std::is_invocable_v<decltype(std::views::join_with), Range, char, char>); | ||
static_assert(!std::is_invocable_v<decltype(std::views::join_with), NonCopyablePattern>); | ||
} | ||
|
||
{ | ||
static_assert(std::is_same_v<decltype(std::ranges::views::join_with), decltype(std::views::join_with)>); | ||
assert(std::addressof(std::ranges::views::join_with) == std::addressof(std::views::join_with)); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
45 changes: 45 additions & 0 deletions
45
.../test/std/ranges/range.adaptors/range.join.with/range.join.with.overview/example.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// [Example 1: | ||
// vector<string> vs = {"the", "quick", "brown", "fox"}; | ||
// for (char c : vs | views::join_with('-')) { | ||
// cout << c; | ||
// } | ||
// // The above prints the-quick-brown-fox | ||
// - end example] | ||
|
||
#include <ranges> | ||
|
||
#include <algorithm> | ||
#include <string> | ||
#include <string_view> | ||
#include <vector> | ||
|
||
using namespace std::string_view_literals; | ||
|
||
constexpr bool test() { | ||
std::vector<std::string> vs = {"the", "quick", "brown", "fox"}; | ||
std::string result; | ||
for (char c : vs | std::views::join_with('-')) { | ||
result += c; | ||
} | ||
|
||
return std::ranges::equal(result, "the-quick-brown-fox"sv); | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
37 changes: 37 additions & 0 deletions
37
.../std/ranges/range.adaptors/range.join.with/range.join.with.sentinel/ctor.default.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// sentinel() = default; | ||
|
||
#include <ranges> | ||
|
||
#include "../types.h" | ||
|
||
constexpr bool test() { | ||
using Inner = BasicVectorView<char, ViewProperties{.common = false}, forward_iterator>; | ||
using V = BasicVectorView<Inner, ViewProperties{}, forward_iterator>; | ||
using Pattern = Inner; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
static_assert(!std::ranges::common_range<JWV>); | ||
|
||
[[maybe_unused]] std::ranges::sentinel_t<JWV> se; | ||
[[maybe_unused]] std::ranges::sentinel_t<const JWV> cse; | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
71 changes: 71 additions & 0 deletions
71
...td/ranges/range.adaptors/range.join.with/range.join.with.sentinel/ctor.non_const.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// constexpr sentinel(sentinel<!Const> s) | ||
// requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; | ||
|
||
#include <ranges> | ||
|
||
#include <type_traits> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
#include "test_iterators.h" | ||
|
||
constexpr bool test() { | ||
{ // Regular conversion from `!Const` to `Const` sentinel | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, forward_iterator>; | ||
std::vector<Inner> vec = {Inner{11, 12}, Inner{13, 14}}; | ||
|
||
std::ranges::join_with_view jwv(vec, 0); | ||
using JWV = decltype(jwv); | ||
static_assert(!std::ranges::common_range<JWV>); | ||
using CSent = std::ranges::sentinel_t<const JWV>; | ||
|
||
auto se = jwv.end(); | ||
[[maybe_unused]] CSent cse = se; | ||
} | ||
|
||
{ // Test conversion from `Const` to `!Const` (should be invalid) | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, forward_iterator>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; | ||
static_assert(!std::ranges::common_range<JWV>); | ||
|
||
using Sent = std::ranges::sentinel_t<JWV>; | ||
using CSent = std::ranges::sentinel_t<const JWV>; | ||
static_assert(!std::convertible_to<CSent, Sent>); | ||
static_assert(!std::constructible_from<Sent, CSent>); | ||
} | ||
|
||
{ // When `convertible_to<sentinel_t<V>, sentinel_t<Base>>` is not modeled | ||
using V = ConstOppositeView<std::vector<long>>; | ||
using Pattern = std::ranges::single_view<long>; | ||
using JWV = std::ranges::join_with_view<V, Pattern>; | ||
static_assert(!std::ranges::common_range<JWV>); | ||
|
||
using Sent = std::ranges::sentinel_t<JWV>; | ||
using CSent = std::ranges::sentinel_t<const JWV>; | ||
static_assert(!std::convertible_to<CSent, Sent>); | ||
static_assert(!std::constructible_from<Sent, CSent>); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
101 changes: 101 additions & 0 deletions
101
libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.sentinel/eq.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 | ||
|
||
// <ranges> | ||
|
||
// template<bool OtherConst> | ||
// requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> | ||
// friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y); | ||
|
||
#include <ranges> | ||
|
||
#include <cassert> | ||
#include <type_traits> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "../types.h" | ||
#include "test_comparisons.h" | ||
#include "test_iterators.h" | ||
|
||
struct NonCrossConstComparableView : std::ranges::view_base { | ||
using NonConstRange = std::vector<int>; | ||
NonConstRange* begin(); | ||
sentinel_wrapper<NonConstRange*> end(); | ||
|
||
using ConstRange = BasicVectorView<int, ViewProperties{}, forward_iterator>; | ||
ConstRange* begin() const; | ||
sentinel_wrapper<ConstRange*> end() const; | ||
}; | ||
|
||
static_assert(std::ranges::range<NonCrossConstComparableView>); | ||
static_assert(std::ranges::range<const NonCrossConstComparableView>); | ||
|
||
constexpr bool test() { | ||
using Inner = BasicVectorView<int, ViewProperties{.common = false}, cpp20_input_iterator>; | ||
using V = std::vector<Inner>; | ||
using Pattern = std::ranges::single_view<int>; | ||
using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>; | ||
static_assert(!std::ranges::common_range<JWV>); | ||
|
||
{ // Compare iterator<Const> with sentinel<Const> | ||
{ // Const == true | ||
AssertEqualityReturnBool<std::ranges::iterator_t<const JWV>, std::ranges::sentinel_t<const JWV>>(); | ||
const JWV jwv(V{Inner{1, 2}, Inner{4}}, 3); | ||
assert(testEquality(std::ranges::next(jwv.begin(), 4), jwv.end(), true)); | ||
assert(testEquality(jwv.begin(), jwv.end(), false)); | ||
} | ||
|
||
{ // Const == false | ||
AssertEqualityReturnBool<std::ranges::iterator_t<JWV>, std::ranges::sentinel_t<JWV>>(); | ||
JWV jwv(V{Inner{5}, Inner{7, 8}}, 6); | ||
assert(testEquality(std::ranges::next(jwv.begin(), 4), jwv.end(), true)); | ||
assert(testEquality(std::ranges::next(jwv.begin(), 2), jwv.end(), false)); | ||
} | ||
} | ||
|
||
{ // Compare iterator<Const> with sentinel<!Const> | ||
{ // Const == true | ||
AssertEqualityReturnBool<std::ranges::iterator_t<const JWV>, std::ranges::sentinel_t<JWV>>(); | ||
JWV jwv(V{Inner{9, 10}, Inner{12}}, 11); | ||
assert(testEquality(std::ranges::next(std::as_const(jwv).begin(), 4), jwv.end(), true)); | ||
assert(testEquality(std::ranges::next(std::as_const(jwv).begin(), 2), jwv.end(), false)); | ||
} | ||
|
||
{ // Const == false | ||
AssertEqualityReturnBool<std::ranges::iterator_t<JWV>, std::ranges::sentinel_t<const JWV>>(); | ||
JWV jwv(V{Inner{13}, Inner{15, 16}}, 14); | ||
assert(testEquality(std::ranges::next(jwv.begin(), 4), std::as_const(jwv).end(), true)); | ||
assert(testEquality(std::ranges::next(jwv.begin(), 3), std::as_const(jwv).end(), false)); | ||
} | ||
} | ||
|
||
{ // Check invalid comparisons between iterator<Const> and sentinel<!Const> | ||
using JWV2 = std::ranges::join_with_view<NonCrossConstComparableView, Pattern>; | ||
static_assert(!std::ranges::common_range<JWV2>); | ||
|
||
static_assert(!weakly_equality_comparable_with<std::ranges::iterator_t<const JWV2>, std::ranges::sentinel_t<JWV2>>); | ||
static_assert(!weakly_equality_comparable_with<std::ranges::iterator_t<JWV2>, std::ranges::sentinel_t<const JWV2>>); | ||
|
||
// Those should be valid | ||
static_assert(weakly_equality_comparable_with<std::ranges::iterator_t<JWV2>, std::ranges::sentinel_t<JWV2>>); | ||
static_assert( | ||
weakly_equality_comparable_with<std::ranges::iterator_t<const JWV2>, std::ranges::sentinel_t<const JWV2>>); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
int main(int, char**) { | ||
test(); | ||
static_assert(test()); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.