brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 7266912 Raw
245 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 R>14//   requires constructible_from<V, views::all_t<R>> &&15//   constructible_from<Pattern, single_view<range_value_t<InnerRng>>>16// constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);17 18#include <ranges>19 20#include <algorithm>21#include <array>22#include <cassert>23#include <type_traits>24#include <utility>25 26#include "../types.h"27#include "test_iterators.h"28#include "test_range.h"29 30struct MoveOnlyInt {31  MoveOnlyInt()                         = default;32  MoveOnlyInt(MoveOnlyInt&&)            = default;33  MoveOnlyInt& operator=(MoveOnlyInt&&) = default;34 35  constexpr MoveOnlyInt(int val) : val_(val) {}36  constexpr operator int() const { return val_; }37 38  int val_ = 0;39};40 41template <>42struct std::common_type<MoveOnlyInt, int> {43  using type = int;44};45 46template <>47struct std::common_type<int, MoveOnlyInt> {48  using type = int;49};50 51struct OutputView : std::ranges::view_base {52  using It = cpp20_output_iterator<int*>;53  It begin() const;54  sentinel_wrapper<It> end() const;55};56 57static_assert(std::ranges::output_range<OutputView, int>);58static_assert(std::ranges::view<OutputView>);59 60struct InputRange {61  using It = cpp20_input_iterator<int*>;62  It begin() const;63  sentinel_wrapper<It> end() const;64};65 66struct InputView : InputRange, std::ranges::view_base {};67 68static_assert(std::ranges::input_range<InputRange>);69static_assert(std::ranges::input_range<const InputRange>);70static_assert(std::ranges::view<InputView>);71static_assert(std::ranges::input_range<InputView>);72static_assert(std::ranges::input_range<const InputView>);73 74class View : public std::ranges::view_base {75  using OuterRange = std::array<std::array<MoveOnlyInt, 2>, 3>;76 77  static constexpr OuterRange range_on_input_view            = {{{1, 1}, {1, 1}, {1, 1}}};78  static constexpr OuterRange range_on_ref_input_range       = {{{2, 2}, {2, 2}, {2, 2}}};79  static constexpr OuterRange range_on_const_ref_input_range = {{{3, 3}, {3, 3}, {3, 3}}};80  static constexpr OuterRange range_on_owning_input_range    = {{{4, 4}, {4, 4}, {4, 4}}};81 82  const OuterRange* r_;83 84public:85  // Those functions should never be called in this test.86  View(View&&) { assert(false); }87  View(OutputView) { assert(false); }88  View& operator=(View&&) {89    assert(false);90    return *this;91  }92 93  constexpr explicit View(InputView) : r_(&range_on_input_view) {}94  constexpr explicit View(InputRange) = delete;95  constexpr explicit View(std::ranges::ref_view<InputRange>) : r_(&range_on_ref_input_range) {}96  constexpr explicit View(std::ranges::ref_view<const InputRange>) : r_(&range_on_const_ref_input_range) {}97  constexpr explicit View(std::ranges::owning_view<InputRange>) : r_(&range_on_owning_input_range) {}98 99  constexpr auto begin() const { return r_->begin(); }100  constexpr auto end() const { return r_->end(); }101};102 103static_assert(std::ranges::input_range<View>);104static_assert(std::ranges::input_range<const View>);105 106class Pattern : public std::ranges::view_base {107  int val_;108 109public:110  // Those functions should never be called in this test.111  Pattern(Pattern&&) { assert(false); }112  template <class T>113  Pattern(const std::ranges::single_view<T>&) {114    assert(false);115  }116  Pattern& operator=(Pattern&&) {117    assert(false);118    return *this;119  }120 121  template <class T>122  constexpr explicit Pattern(std::ranges::single_view<T>&& v) : val_(v[0]) {}123 124  constexpr const int* begin() const { return &val_; }125  constexpr const int* end() const { return &val_ + 1; }126};127 128static_assert(std::ranges::forward_range<Pattern>);129static_assert(std::ranges::forward_range<const Pattern>);130 131constexpr void test_ctor_with_view_and_element() {132  // Check construction from `r` and `e`, when `r` models `std::ranges::view`133 134  { // `r` and `e` are glvalues135    InputView r;136    int e = 0;137    std::ranges::join_with_view<View, Pattern> jwv(r, e);138    assert(std::ranges::equal(jwv, std::array{1, 1, 0, 1, 1, 0, 1, 1}));139  }140 141  { // `r` and `e` are const glvalues142    const InputView r;143    const int e = 1;144    std::ranges::join_with_view<View, Pattern> jwv(r, e);145    assert(std::ranges::equal(jwv, std::array{1, 1, 1, 1, 1, 1, 1, 1}));146  }147 148  { // `r` and `e` are prvalues149    std::ranges::join_with_view<View, Pattern> jwv(InputView{}, MoveOnlyInt{2});150    assert(std::ranges::equal(jwv, std::array{1, 1, 2, 1, 1, 2, 1, 1}));151  }152 153  { // `r` and `e` are xvalues154    InputView r;155    MoveOnlyInt e = 3;156    std::ranges::join_with_view<View, Pattern> jwv(std::move(r), std::move(e));157    assert(std::ranges::equal(jwv, std::array{1, 1, 3, 1, 1, 3, 1, 1}));158  }159 160  // Check explicitness161  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputView, MoveOnlyInt>);162  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputView, int>);163  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputView&, int&>);164  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, const InputView, const int>);165  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, const InputView&, const int&>);166}167 168constexpr void test_ctor_with_non_view_and_element() {169  // Check construction from `r` and `e`, when `r` does not model `std::ranges::view`170 171  { // `r` and `e` are glvalues172    InputRange r;173    int e = 0;174    std::ranges::join_with_view<View, Pattern> jwv(r, e);175    assert(std::ranges::equal(jwv, std::array{2, 2, 0, 2, 2, 0, 2, 2}));176  }177 178  { // `r` and `e` are const glvalues179    const InputRange r;180    const int e = 1;181    std::ranges::join_with_view<View, Pattern> jwv(r, e);182    assert(std::ranges::equal(jwv, std::array{3, 3, 1, 3, 3, 1, 3, 3}));183  }184 185  { // `r` and `e` are prvalues186    std::ranges::join_with_view<View, Pattern> jwv(InputRange{}, MoveOnlyInt{2});187    assert(std::ranges::equal(jwv, std::array{4, 4, 2, 4, 4, 2, 4, 4}));188  }189 190  { // `r` and `e` are xvalues191    InputRange r;192    MoveOnlyInt e = 3;193    std::ranges::join_with_view<View, Pattern> jwv(std::move(r), std::move(e));194    assert(std::ranges::equal(jwv, std::array{4, 4, 3, 4, 4, 3, 4, 4}));195  }196 197  // Check explicitness198  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputRange, MoveOnlyInt>);199  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputRange, int>);200  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, InputRange&, int&>);201  static_assert(ConstructionIsExplicit<std::ranges::join_with_view<View, Pattern>, const InputRange&, const int&>);202}203 204constexpr void test_constraints() {205  { // `R` is not an input range206    using R = OutputView;207    static_assert(!std::ranges::input_range<R>);208    static_assert(std::constructible_from<View, std::views::all_t<R>>);209    static_assert(std::constructible_from<Pattern, std::ranges::single_view<int>>);210    static_assert(!std::constructible_from<std::ranges::join_with_view<View, Pattern>, R, int>);211  }212 213  { // `V` is not constructible from `views::all_t<R>`214    using R = test_range<cpp20_input_iterator>;215    static_assert(std::ranges::input_range<R>);216    static_assert(!std::constructible_from<View, std::views::all_t<R>>);217    static_assert(std::constructible_from<Pattern, std::ranges::single_view<int>>);218    static_assert(!std::constructible_from<std::ranges::join_with_view<View, Pattern>, R, int>);219  }220 221  { // `Pattern` is not constructible from `single_view<range_value_t<InnerRng>>`222    using R   = InputView;223    using Pat = test_view<forward_iterator>;224    static_assert(std::ranges::input_range<R>);225    static_assert(std::constructible_from<View, std::views::all_t<R>>);226    static_assert(!std::constructible_from<Pat, std::ranges::single_view<int>>);227    static_assert(!std::constructible_from<std::ranges::join_with_view<View, Pat>, R, int>);228  }229}230 231constexpr bool test() {232  test_ctor_with_view_and_element();233  test_ctor_with_non_view_and_element();234  test_constraints();235 236  return true;237}238 239int main(int, char**) {240  test();241  static_assert(test());242 243  return 0;244}245