1a2b3ab8fSHui //===----------------------------------------------------------------------===//
2a2b3ab8fSHui //
3a2b3ab8fSHui // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a2b3ab8fSHui // See https://llvm.org/LICENSE.txt for license information.
5a2b3ab8fSHui // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a2b3ab8fSHui //
7a2b3ab8fSHui //===----------------------------------------------------------------------===//
8a2b3ab8fSHui
9a2b3ab8fSHui // UNSUPPORTED: c++03, c++11, c++14, c++17
10a2b3ab8fSHui
1140aaa272SHristo Hristov // constexpr split_view(View base, Pattern pattern); // explicit since C++23
12a2b3ab8fSHui
13a2b3ab8fSHui #include <algorithm>
14a2b3ab8fSHui #include <cassert>
15a2b3ab8fSHui #include <ranges>
16a2b3ab8fSHui #include <string_view>
17a2b3ab8fSHui #include <utility>
18a2b3ab8fSHui
1940aaa272SHristo Hristov #include "test_convertible.h"
2040aaa272SHristo Hristov #include "test_macros.h"
2140aaa272SHristo Hristov
22a2b3ab8fSHui struct ViewWithCounting : std::ranges::view_base {
23a2b3ab8fSHui int* times_copied = nullptr;
24a2b3ab8fSHui int* times_moved = nullptr;
25a2b3ab8fSHui
ViewWithCountingViewWithCounting26a2b3ab8fSHui constexpr ViewWithCounting(int& copies_ctr, int& moves_ctr) : times_copied(&copies_ctr), times_moved(&moves_ctr) {}
27a2b3ab8fSHui
ViewWithCountingViewWithCounting28a2b3ab8fSHui constexpr ViewWithCounting(const ViewWithCounting& rhs)
29a2b3ab8fSHui : times_copied(rhs.times_copied), times_moved(rhs.times_moved) {
30a2b3ab8fSHui ++(*times_copied);
31a2b3ab8fSHui }
ViewWithCountingViewWithCounting32a2b3ab8fSHui constexpr ViewWithCounting(ViewWithCounting&& rhs) : times_copied(rhs.times_copied), times_moved(rhs.times_moved) {
33a2b3ab8fSHui ++(*times_moved);
34a2b3ab8fSHui }
35a2b3ab8fSHui
beginViewWithCounting36a2b3ab8fSHui constexpr const char* begin() const { return nullptr; }
endViewWithCounting37a2b3ab8fSHui constexpr const char* end() const { return nullptr; }
38a2b3ab8fSHui
39a2b3ab8fSHui constexpr ViewWithCounting& operator=(const ViewWithCounting&) = default;
40a2b3ab8fSHui constexpr ViewWithCounting& operator=(ViewWithCounting&&) = default;
operator ==ViewWithCounting41a2b3ab8fSHui constexpr bool operator==(const ViewWithCounting&) const { return true; }
42a2b3ab8fSHui };
43a2b3ab8fSHui
4440aaa272SHristo Hristov using View = ViewWithCounting;
4540aaa272SHristo Hristov using Pattern = ViewWithCounting;
4640aaa272SHristo Hristov
4740aaa272SHristo Hristov // SFINAE tests.
4840aaa272SHristo Hristov
4940aaa272SHristo Hristov #if TEST_STD_VER >= 23
5040aaa272SHristo Hristov
5140aaa272SHristo Hristov static_assert(!test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
5240aaa272SHristo Hristov "This constructor must be explicit");
5340aaa272SHristo Hristov
5440aaa272SHristo Hristov #else
5540aaa272SHristo Hristov
5640aaa272SHristo Hristov static_assert( test_convertible<std::ranges::split_view<View, Pattern>, View, Pattern>(),
5740aaa272SHristo Hristov "This constructor must not be explicit");
5840aaa272SHristo Hristov
5940aaa272SHristo Hristov #endif // TEST_STD_VER >= 23
6040aaa272SHristo Hristov
test()61a2b3ab8fSHui constexpr bool test() {
62a2b3ab8fSHui {
63a2b3ab8fSHui std::string_view input = "abc def";
64*88171885SKonstantin Varlamov std::ranges::split_view<std::string_view, std::string_view> v(input, " ");
65a2b3ab8fSHui assert(v.base() == input);
66a2b3ab8fSHui assert(std::ranges::equal(*v.begin(), std::string_view{"abc"}));
67a2b3ab8fSHui }
68a2b3ab8fSHui
69a2b3ab8fSHui // Make sure the arguments are moved, not copied.
70a2b3ab8fSHui {
71a2b3ab8fSHui // Arguments are lvalues.
72a2b3ab8fSHui {
73a2b3ab8fSHui int view_copied = 0, view_moved = 0, pattern_copied = 0, pattern_moved = 0;
74a2b3ab8fSHui View view(view_copied, view_moved);
75a2b3ab8fSHui Pattern pattern(pattern_copied, pattern_moved);
76a2b3ab8fSHui
77a2b3ab8fSHui std::ranges::split_view<View, Pattern> v(view, pattern);
78a2b3ab8fSHui assert(view_copied == 1); // The local variable is copied into the argument.
79a2b3ab8fSHui assert(view_moved == 1);
80a2b3ab8fSHui assert(pattern_copied == 1);
81a2b3ab8fSHui assert(pattern_moved == 1);
82a2b3ab8fSHui }
83a2b3ab8fSHui
84a2b3ab8fSHui // Arguments are rvalues.
85a2b3ab8fSHui {
86a2b3ab8fSHui int view_copied = 0, view_moved = 0, pattern_copied = 0, pattern_moved = 0;
87a2b3ab8fSHui std::ranges::split_view<View, Pattern> v(View(view_copied, view_moved), Pattern(pattern_copied, pattern_moved));
88a2b3ab8fSHui assert(view_copied == 0);
89a2b3ab8fSHui assert(view_moved == 1);
90a2b3ab8fSHui assert(pattern_copied == 0);
91a2b3ab8fSHui assert(pattern_moved == 1);
92a2b3ab8fSHui }
93a2b3ab8fSHui }
94a2b3ab8fSHui
95a2b3ab8fSHui return true;
96a2b3ab8fSHui }
97a2b3ab8fSHui
main(int,char **)98a2b3ab8fSHui int main(int, char**) {
99a2b3ab8fSHui test();
100a2b3ab8fSHui static_assert(test());
101a2b3ab8fSHui
102a2b3ab8fSHui return 0;
103a2b3ab8fSHui }
104