| 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | // REQUIRES: std-at-least-c++23 |
| 10 | |
| 11 | // <ranges> |
| 12 | |
| 13 | // constexpr iterator(iterator<!Const> i) |
| 14 | // requires Const && convertible_to<iterator_t<V>, OuterIter> && |
| 15 | // convertible_to<iterator_t<InnerRng>, InnerIter> && |
| 16 | // convertible_to<iterator_t<Pattern>, PatternIter>; |
| 17 | |
| 18 | #include <ranges> |
| 19 | |
| 20 | #include <cassert> |
| 21 | #include <vector> |
| 22 | |
| 23 | #include "../types.h" |
| 24 | |
| 25 | constexpr bool test() { |
| 26 | { // Regular conversion from `!Const` to `Const` iterator |
| 27 | std::vector<std::vector<int>> vec = {{1, 2}, {3, 4}, {5, 6}}; |
| 28 | int pattern = 0; |
| 29 | std::ranges::join_with_view jwv(vec, pattern); |
| 30 | |
| 31 | using JWV = decltype(jwv); |
| 32 | using Iter = std::ranges::iterator_t<JWV>; |
| 33 | using CIter = std::ranges::iterator_t<const JWV>; |
| 34 | static_assert(!std::same_as<Iter, CIter>); |
| 35 | static_assert(std::convertible_to<Iter, CIter>); |
| 36 | static_assert(std::constructible_from<CIter, Iter>); |
| 37 | |
| 38 | Iter it = jwv.begin(); |
| 39 | assert(*it == 1); |
| 40 | |
| 41 | const CIter cit1 = it; // `cit1` points to element of `V`; this constructor should not be explicit |
| 42 | assert(*cit1 == 1); |
| 43 | assert(cit1 == it); |
| 44 | |
| 45 | std::ranges::advance(it, 2); |
| 46 | assert(*it == 0); |
| 47 | CIter cit2 = it; // `cit2` points to element of `Pattern` |
| 48 | assert(*cit2 == 0); |
| 49 | assert(cit2 == it); |
| 50 | |
| 51 | ++it; |
| 52 | assert(*it == 3); |
| 53 | CIter cit3 = it; |
| 54 | assert(*cit3 == 3); |
| 55 | assert(cit3 == it); |
| 56 | |
| 57 | --cit3; |
| 58 | assert(cit2 == cit3); |
| 59 | } |
| 60 | |
| 61 | { // Test conversion from `Const` to `!Const` (should be invalid) |
| 62 | using V = std::vector<std::vector<int>>; |
| 63 | using Pattern = std::ranges::single_view<int>; |
| 64 | using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; |
| 65 | using Iter = std::ranges::iterator_t<JWV>; |
| 66 | using CIter = std::ranges::iterator_t<const JWV>; |
| 67 | static_assert(!std::convertible_to<CIter, Iter>); |
| 68 | static_assert(!std::constructible_from<Iter, CIter>); |
| 69 | } |
| 70 | |
| 71 | { // When `convertible_to<iterator_t<V>, OuterIter>` is not modeled |
| 72 | using Inner = std::vector<short>; |
| 73 | using V = ConstOppositeView<Inner>; |
| 74 | using Pattern = std::ranges::single_view<short>; |
| 75 | using JWV = std::ranges::join_with_view<V, Pattern>; |
| 76 | using Iter = std::ranges::iterator_t<JWV>; |
| 77 | using CIter = std::ranges::iterator_t<const JWV>; |
| 78 | static_assert(!std::convertible_to<CIter, Iter>); |
| 79 | static_assert(!std::constructible_from<Iter, CIter>); |
| 80 | } |
| 81 | |
| 82 | { // When `convertible_to<iterator_t<InnerRng>, InnerIter>` is not modeled |
| 83 | using Inner = ConstOppositeView<long>; |
| 84 | using V = std::vector<Inner>; |
| 85 | using Pattern = std::ranges::single_view<long>; |
| 86 | using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; |
| 87 | using Iter = std::ranges::iterator_t<JWV>; |
| 88 | using CIter = std::ranges::iterator_t<const JWV>; |
| 89 | static_assert(!std::convertible_to<CIter, Iter>); |
| 90 | static_assert(!std::constructible_from<Iter, CIter>); |
| 91 | } |
| 92 | |
| 93 | { // When `convertible_to<iterator_t<Pattern>, PatternIter>` is not modeled |
| 94 | using V = std::vector<std::vector<long long>>; |
| 95 | using Pattern = ConstOppositeView<long long>; |
| 96 | using JWV = std::ranges::join_with_view<std::views::all_t<V>, Pattern>; |
| 97 | using Iter = std::ranges::iterator_t<JWV>; |
| 98 | using CIter = std::ranges::iterator_t<const JWV>; |
| 99 | static_assert(!std::convertible_to<CIter, Iter>); |
| 100 | static_assert(!std::constructible_from<Iter, CIter>); |
| 101 | } |
| 102 | |
| 103 | return true; |
| 104 | } |
| 105 | |
| 106 | int main(int, char**) { |
| 107 | test(); |
| 108 | static_assert(test()); |
| 109 | |
| 110 | return 0; |
| 111 | } |
| 112 | |