brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.6 KiB · c6e973a Raw
233 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// constexpr auto end();14// constexpr auto end() const15//   requires forward_range<const V> && forward_range<const Pattern> &&16//            is_reference_v<range_reference_t<const V>> &&17//            input_range<range_reference_t<const V>>;18 19// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=1000000020 21#include <ranges>22 23#include <algorithm>24#include <string>25#include <vector>26 27#include "../types.h"28#include "test_iterators.h"29 30template <class V, class Pattern>31concept JoinWithViewHasConstEnd = requires(const std::ranges::join_with_view<V, Pattern> jwv) { jwv.end(); };32 33template <size_t Bits>34  requires(Bits < (1 << 7))35constexpr void test_end() {36  constexpr bool v_models_forward_range           = static_cast<bool>(Bits & (1 << 0));37  constexpr bool inner_range_is_reference         = static_cast<bool>(Bits & (1 << 1));38  constexpr bool inner_range_models_forward_range = static_cast<bool>(Bits & (1 << 2));39  constexpr bool v_models_common_range            = static_cast<bool>(Bits & (1 << 3));40  constexpr bool inner_range_models_common_range  = static_cast<bool>(Bits & (1 << 4));41  constexpr bool v_models_simple_range            = static_cast<bool>(Bits & (1 << 5));42  constexpr bool pattern_models_simple_range      = static_cast<bool>(Bits & (1 << 6));43 44  constexpr ViewProperties inner_range_props{.common = inner_range_models_common_range};45  using InnerRange =46      std::conditional_t<inner_range_models_forward_range,47                         BasicView<std::vector<int>, inner_range_props, forward_iterator>,48                         BasicView<std::vector<int>, inner_range_props, DefaultCtorInputIter>>;49 50  constexpr ViewProperties v_props{.simple = v_models_simple_range, .common = v_models_common_range};51  using UnderlyingV = std::conditional_t<inner_range_is_reference, std::vector<InnerRange>, RvalueVector<InnerRange>>;52  using V           = std::conditional_t<v_models_forward_range,53                                         BasicView<UnderlyingV, v_props, forward_iterator>,54                                         BasicView<UnderlyingV, v_props, DefaultCtorInputIter>>;55 56  using UnderlyingPattern = std::vector<int>;57  using Pattern = BasicView<UnderlyingPattern, ViewProperties{.simple = pattern_models_simple_range}, forward_iterator>;58 59  using JWV  = std::ranges::join_with_view<V, Pattern>;60  using Iter = std::ranges::iterator_t<JWV>;61 62  // Test when `JWV` models common range63  static_assert(std::same_as<Iter, std::ranges::sentinel_t<JWV>> ==64                (v_models_forward_range && inner_range_is_reference && inner_range_models_forward_range &&65                 v_models_common_range && inner_range_models_common_range));66 67  { // `V` and `Pattern` are empty68    V v{};69    Pattern pattern{};70    JWV jwv(std::move(v), std::move(pattern));71    Iter it                                   = jwv.begin();72    std::sentinel_for<Iter> decltype(auto) se = jwv.end();73    assert(it == se);74  }75 76  { // `V` is empty, `Pattern` contains some elements77    V v{};78    Pattern pattern{std::vector<int>{0}};79    JWV jwv(std::move(v), std::move(pattern));80    Iter it                                   = jwv.begin();81    std::sentinel_for<Iter> decltype(auto) se = jwv.end();82    assert(it == se);83  }84 85  { // `V` is not empty, `Pattern is empty`86    V v{UnderlyingV{87        std::vector<InnerRange>{InnerRange(std::vector<int>{1, 2, 3}), InnerRange(std::vector<int>{4, 5, 6})}}};88    Pattern pattern{};89    JWV jwv(std::move(v), std::move(pattern));90    Iter it                                   = jwv.begin();91    std::sentinel_for<Iter> decltype(auto) se = jwv.end();92    assert(std::ranges::next(it, 6) == se);93  }94 95  { // `V` and `Pattern` are not empty96    V v{UnderlyingV{std::vector<InnerRange>{97        InnerRange(std::vector<int>{6, 5}),98        InnerRange(std::vector<int>{4, 3}),99        InnerRange(std::vector<int>{2, 1, 0})}}};100    Pattern pattern{std::vector<int>{-1, -1}};101    JWV jwv(std::move(v), std::move(pattern));102    Iter it                                   = jwv.begin();103    std::sentinel_for<Iter> decltype(auto) se = jwv.end();104    assert(std::ranges::next(it, 11) == se);105  }106}107 108template <std::size_t Bits>109  requires(Bits < (1 << 7))110constexpr void test_const_end() {111  constexpr bool const_v_models_forward_range           = static_cast<bool>(Bits & (1 << 0));112  constexpr bool const_pattern_models_forward_range     = static_cast<bool>(Bits & (1 << 1));113  constexpr bool inner_const_range_is_reference         = static_cast<bool>(Bits & (1 << 2));114  constexpr bool inner_const_range_models_input_range   = static_cast<bool>(Bits & (1 << 3));115  constexpr bool inner_const_range_models_forward_range = static_cast<bool>(Bits & (1 << 4));116  constexpr bool const_v_models_common_range            = static_cast<bool>(Bits & (1 << 5));117  constexpr bool inner_const_range_models_common_range  = static_cast<bool>(Bits & (1 << 6));118 119  constexpr ViewProperties inner_range_props{.common = inner_const_range_models_common_range};120  using InnerRange =121      std::conditional_t<inner_const_range_models_forward_range,122                         BasicView<std::vector<int>, inner_range_props, forward_iterator>,123                         std::conditional_t<inner_const_range_models_input_range,124                                            BasicView<std::vector<int>, inner_range_props, DefaultCtorInputIter>,125                                            InputRangeButOutputWhenConst<int>>>;126 127  constexpr ViewProperties v_props{.common = const_v_models_common_range};128  using UnderlyingV =129      std::conditional_t<inner_const_range_is_reference, std::vector<InnerRange>, RvalueVector<InnerRange>>;130  using V = std::conditional_t<const_v_models_forward_range,131                               BasicView<UnderlyingV, v_props, forward_iterator>,132                               BasicView<UnderlyingV, v_props, DefaultCtorInputIter>>;133  using Pattern =134      std::conditional_t<const_pattern_models_forward_range,135                         BasicView<std::vector<int>, ViewProperties{}, forward_iterator>,136                         ForwardViewButInputWhenConst<int>>;137 138  using JWV = std::ranges::join_with_view<V, Pattern>;139  static_assert(JoinWithViewHasConstEnd<V, Pattern> ==140                (const_v_models_forward_range && const_pattern_models_forward_range && inner_const_range_is_reference &&141                 (inner_const_range_models_input_range || inner_const_range_models_forward_range)));142  static_assert(JoinWithViewHasConstEnd<V, Pattern> == std::ranges::range<const JWV>);143 144  if constexpr (std::ranges::range<const JWV>) {145    using ConstIter = std::ranges::iterator_t<const JWV>;146 147    // Test when `const JWV` models common range148    static_assert(std::same_as<ConstIter, std::ranges::sentinel_t<const JWV>> ==149                  (inner_const_range_models_forward_range && const_v_models_common_range &&150                   inner_const_range_models_common_range));151 152    { // `const V` and `const Pattern` are empty153      V v{};154      Pattern pattern{};155      const JWV jwv(std::move(v), std::move(pattern));156      ConstIter it                                   = jwv.begin();157      std::sentinel_for<ConstIter> decltype(auto) se = jwv.end();158      assert(it == se);159    }160 161    { // `const V` is empty, `const Pattern` contains some elements162      V v{};163      Pattern pattern{std::vector<int>{1}};164      const JWV jwv(std::move(v), std::move(pattern));165      ConstIter it                                   = jwv.begin();166      std::sentinel_for<ConstIter> decltype(auto) se = jwv.end();167      assert(it == se);168    }169 170    { // `const V` is not empty, `const Pattern is empty`171      V v{UnderlyingV{172          std::vector<InnerRange>{InnerRange(std::vector<int>{1, 2, 3}), InnerRange(std::vector<int>{4, 5, 6})}}};173      Pattern pattern{};174      const JWV jwv(std::move(v), std::move(pattern));175      ConstIter it                                   = jwv.begin();176      std::sentinel_for<ConstIter> decltype(auto) se = jwv.end();177      assert(std::ranges::next(it, 6) == se);178    }179 180    { // `const V` and `const Pattern` are not empty181      V v{UnderlyingV{std::vector<InnerRange>{182          InnerRange(std::vector<int>{1}), InnerRange(std::vector<int>{2, 2}), InnerRange(std::vector<int>{3, 3, 3})}}};183      Pattern pattern{std::vector<int>{0}};184      const JWV jwv(std::move(v), std::move(pattern));185      ConstIter it                                   = jwv.begin();186      std::sentinel_for<ConstIter> decltype(auto) se = jwv.end();187      assert(std::ranges::next(it, 8) == se);188    }189  }190}191 192constexpr bool test() {193  []<std::size_t... Bits>(std::index_sequence<Bits...>) {194    (test_end<Bits>(), ...);195    (test_const_end<Bits>(), ...);196  }(std::make_index_sequence<(1 << 7)>{});197 198  { // Check situation when iterators returned by `end()` and `end() const` are of the same type199    using V             = BasicView<std::vector<std::string>, ViewProperties{.simple = true}, forward_iterator>;200    using Pattern       = BasicView<std::string, ViewProperties{.simple = true}, forward_iterator>;201    using JWV           = std::ranges::join_with_view<V, Pattern>;202    using Sentinel      = std::ranges::sentinel_t<JWV&>;203    using ConstSentinel = std::ranges::sentinel_t<const JWV&>;204    static_assert(std::input_iterator<Sentinel>);205    static_assert(std::input_iterator<ConstSentinel>);206    static_assert(std::same_as<Sentinel, ConstSentinel>);207  }208 209  { // Check situation when sentinels returned by `end()` and `end() const` are of the same type210    using V = BasicView<std::vector<std::string>, ViewProperties{.simple = true, .common = false}, forward_iterator>;211    using Pattern       = BasicView<std::string, ViewProperties{.simple = true}, forward_iterator>;212    using JWV           = std::ranges::join_with_view<V, Pattern>;213    using Sentinel      = std::ranges::sentinel_t<JWV&>;214    using ConstSentinel = std::ranges::sentinel_t<const JWV&>;215    static_assert(!std::input_iterator<Sentinel>);216    static_assert(!std::input_iterator<ConstSentinel>);217    static_assert(std::same_as<Sentinel, ConstSentinel>);218  }219 220  // Check LWG-4074: compatible-joinable-ranges is underconstrained221  static_assert(!JoinWithViewHasConstEnd<BasicVectorView<int, ViewProperties{}, forward_iterator>,222                                         lwg4074::PatternWithProxyConstAccess>);223 224  return true;225}226 227int main(int, char**) {228  test();229  static_assert(test());230 231  return 0;232}233