290 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: std-at-least-c++2310 11// <ranges>12 13// template <input_range V, forward_range Pattern>14// requires view<V> && input_range<range_reference_t<V>> && view<Pattern> &&15// compatible-joinable-ranges<range_reference_t<V>, Pattern>16// class join_with_view;17 18#include <ranges>19 20#include <cstddef>21#include <vector>22 23#include "test_iterators.h"24#include "../types.h"25 26template <class View, class Pattern>27concept CanFormJoinWithView = requires { typename std::ranges::join_with_view<View, Pattern>; };28 29// join_with_view is not valid when `V` is not an input_range30namespace test_when_view_is_not_an_input_range {31struct View : std::ranges::view_base {32 using It = cpp20_output_iterator<std::vector<int>*>;33 It begin();34 sentinel_wrapper<It> end();35};36 37struct Pattern : std::ranges::view_base {38 int* begin();39 int* end();40};41 42static_assert(std::ranges::range<View>);43static_assert(!std::ranges::input_range<View>);44static_assert(std::ranges::view<View>);45static_assert(std::ranges::forward_range<Pattern>);46static_assert(std::ranges::view<Pattern>);47static_assert(!CanFormJoinWithView<View, Pattern>);48} // namespace test_when_view_is_not_an_input_range49 50// join_with_view is not valid when `Pattern` is not a forward_range51namespace test_when_pattern_is_not_a_forward_range {52struct View : std::ranges::view_base {53 std::vector<float>* begin();54 std::vector<float>* end();55};56 57struct Pattern : std::ranges::view_base {58 using It = cpp20_input_iterator<float*>;59 It begin();60 sentinel_wrapper<It> end();61};62 63static_assert(std::ranges::input_range<View>);64static_assert(std::ranges::view<View>);65static_assert(!std::ranges::forward_range<Pattern>);66static_assert(std::ranges::view<Pattern>);67static_assert(!CanFormJoinWithView<View, Pattern>);68} // namespace test_when_pattern_is_not_a_forward_range69 70// join_with_view is not valid when `V` does not model std::ranges::view71namespace test_when_view_does_not_model_view {72struct View {73 std::vector<double>* begin();74 std::vector<double>* end();75};76 77struct Pattern : std::ranges::view_base {78 double* begin();79 double* end();80};81 82static_assert(std::ranges::input_range<View>);83static_assert(!std::ranges::view<View>);84static_assert(std::ranges::forward_range<Pattern>);85static_assert(std::ranges::view<Pattern>);86static_assert(!CanFormJoinWithView<View, Pattern>);87} // namespace test_when_view_does_not_model_view88 89// join_with_view is not valid when `range_reference_t` of `V` is not an input_range90namespace test_when_range_reference_t_of_view_is_not_an_input_range {91struct InnerRange {92 using It = cpp20_output_iterator<long*>;93 It begin();94 sentinel_wrapper<It> end();95};96 97struct View : std::ranges::view_base {98 InnerRange* begin();99 InnerRange* end();100};101 102struct Pattern : std::ranges::view_base {103 long* begin();104 long* end();105};106 107static_assert(std::ranges::range<InnerRange>);108static_assert(!std::ranges::input_range<InnerRange>);109static_assert(std::ranges::input_range<View>);110static_assert(std::ranges::view<View>);111static_assert(std::ranges::forward_range<Pattern>);112static_assert(std::ranges::view<Pattern>);113static_assert(!CanFormJoinWithView<View, Pattern>);114} // namespace test_when_range_reference_t_of_view_is_not_an_input_range115 116// join_with_view is not valid when `Pattern` does not model std::ranges::view117namespace test_when_pattern_does_not_model_view {118struct View : std::ranges::view_base {119 std::vector<short>* begin();120 std::vector<short>* end();121};122 123struct Pattern {124 short* begin();125 short* end();126};127 128static_assert(std::ranges::input_range<View>);129static_assert(std::ranges::view<View>);130static_assert(std::ranges::forward_range<Pattern>);131static_assert(!std::ranges::view<Pattern>);132static_assert(!CanFormJoinWithView<View, Pattern>);133} // namespace test_when_pattern_does_not_model_view134 135// join_with_view is not valid when `range_reference_t<View>` and pattern136// does not model together compatible-joinable-ranges137namespace test_when_used_ranges_are_not_concatable {138using std::ranges::range_reference_t;139using std::ranges::range_rvalue_reference_t;140using std::ranges::range_value_t;141 142template <class InnerRange>143struct View : std::ranges::view_base {144 InnerRange* begin();145 InnerRange* end();146};147 148namespace no_concat_reference_t {149struct ValueType {};150 151struct InnerRange {152 struct It {153 using difference_type = std::ptrdiff_t;154 using value_type = ValueType;155 struct reference {156 operator value_type();157 };158 159 It& operator++();160 void operator++(int);161 reference operator*() const;162 };163 164 It begin();165 sentinel_wrapper<It> end();166};167 168struct Pattern : std::ranges::view_base {169 struct It {170 using difference_type = std::ptrdiff_t;171 using value_type = ValueType;172 struct reference {173 operator value_type();174 };175 176 It& operator++();177 It operator++(int);178 reference operator*() const;179 bool operator==(const It&) const;180 friend value_type&& iter_move(const It&);181 };182 183 It begin();184 It end();185};186 187static_assert(std::ranges::input_range<InnerRange>);188static_assert(std::ranges::forward_range<Pattern>);189static_assert(std::ranges::view<Pattern>);190static_assert(!std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);191static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);192static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);193static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);194} // namespace no_concat_reference_t195 196namespace no_concat_value_t {197struct InnerRange {198 struct It {199 using difference_type = std::ptrdiff_t;200 struct value_type {};201 202 struct reference {203 operator value_type();204 operator float();205 };206 207 It& operator++();208 void operator++(int);209 reference operator*() const;210 };211 212 It begin();213 sentinel_wrapper<It> end();214};215 216struct Pattern : std::ranges::view_base {217 const float* begin();218 const float* end();219};220 221static_assert(std::ranges::input_range<InnerRange>);222static_assert(std::ranges::forward_range<Pattern>);223static_assert(std::ranges::view<Pattern>);224static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);225static_assert(!std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);226static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);227static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);228} // namespace no_concat_value_t229 230namespace no_concat_rvalue_reference_t {231struct InnerRange {232 using It = cpp20_input_iterator<int*>;233 It begin();234 sentinel_wrapper<It> end();235};236 237struct Pattern : std::ranges::view_base {238 struct It {239 using difference_type = std::ptrdiff_t;240 struct value_type {241 operator int() const;242 };243 244 struct rvalue_reference {245 operator value_type();246 };247 248 It& operator++();249 It operator++(int);250 value_type& operator*() const;251 bool operator==(const It&) const;252 friend rvalue_reference iter_move(const It&);253 };254 255 It begin();256 It end();257};258 259static_assert(std::ranges::input_range<InnerRange>);260static_assert(std::ranges::forward_range<Pattern>);261static_assert(std::ranges::view<Pattern>);262static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);263static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);264static_assert(!std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);265static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);266} // namespace no_concat_rvalue_reference_t267 268namespace not_concat_indirectly_readable { // Required after LWG-4074 ("compatible-joinable-ranges is underconstrained")269struct InnerRange {270 using It = cpp20_input_iterator<int*>;271 It begin();272 sentinel_wrapper<It> end();273};274 275struct Pattern : std::ranges::view_base {276 lwg4074::Iter begin();277 lwg4074::Iter end();278};279 280static_assert(std::ranges::input_range<InnerRange>);281static_assert(std::ranges::forward_range<Pattern>);282static_assert(std::ranges::view<Pattern>);283static_assert(std::common_reference_with<range_reference_t<InnerRange>, range_reference_t<Pattern>>);284static_assert(std::common_with<range_value_t<InnerRange>, range_value_t<Pattern>>);285static_assert(std::common_reference_with<range_rvalue_reference_t<InnerRange>, range_rvalue_reference_t<Pattern>>);286LIBCPP_STATIC_ASSERT(!std::ranges::__concat_indirectly_readable<InnerRange, Pattern>);287static_assert(!CanFormJoinWithView<View<InnerRange>, Pattern>);288} // namespace not_concat_indirectly_readable289} // namespace test_when_used_ranges_are_not_concatable290