brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 88e7179 Raw
209 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// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<range R>12//  requires is_object_v<R>13// class ref_view;14 15#include <ranges>16 17#include <cassert>18#include "test_macros.h"19#include "test_iterators.h"20 21int globalBuff[8];22 23template<class T>24concept ValidRefView = requires { typename std::ranges::ref_view<T>; };25 26struct Range {27  int start = 0;28  friend constexpr int* begin(Range const& range) { return globalBuff + range.start; }29  friend constexpr int* end(Range const&) { return globalBuff + 8; }30  friend constexpr int* begin(Range& range) { return globalBuff + range.start; }31  friend constexpr int* end(Range&) { return globalBuff + 8; }32};33 34struct BeginOnly {35  friend int* begin(BeginOnly const&);36  friend int* begin(BeginOnly &);37};38 39static_assert( ValidRefView<Range>);40static_assert(!ValidRefView<BeginOnly>);41static_assert(!ValidRefView<int (&)[4]>);42static_assert( ValidRefView<int[4]>);43 44static_assert(std::derived_from<std::ranges::ref_view<Range>, std::ranges::view_interface<std::ranges::ref_view<Range>>>);45 46struct RangeConvertible {47  operator Range& ();48};49 50struct RValueRangeConvertible {51  operator Range&& ();52};53 54static_assert( std::is_constructible_v<std::ranges::ref_view<Range>, Range&>);55static_assert( std::is_constructible_v<std::ranges::ref_view<Range>, RangeConvertible>);56static_assert(!std::is_constructible_v<std::ranges::ref_view<Range>, RValueRangeConvertible>);57 58struct ConstConvertibleToLValueAndRValue {59  operator Range& () const;60  operator Range&& () const;61};62static_assert( std::is_convertible_v<RangeConvertible, std::ranges::ref_view<Range>>);63static_assert(!std::is_convertible_v<RValueRangeConvertible, std::ranges::ref_view<Range>>);64static_assert(!std::is_convertible_v<ConstConvertibleToLValueAndRValue, std::ranges::ref_view<Range>>);65 66struct ForwardRange {67  constexpr forward_iterator<int*> begin() const { return forward_iterator<int*>(globalBuff); }68  constexpr forward_iterator<int*> end() const { return forward_iterator<int*>(globalBuff + 8); }69};70 71struct Cpp17InputRange {72  struct sentinel {73    friend constexpr bool operator==(sentinel, cpp17_input_iterator<int*> iter) { return base(iter) == globalBuff + 8; }74    friend constexpr std::ptrdiff_t operator-(sentinel, cpp17_input_iterator<int*>) { return -8; }75    friend constexpr std::ptrdiff_t operator-(cpp17_input_iterator<int*>, sentinel) { return 8; }76  };77 78  constexpr cpp17_input_iterator<int*> begin() const {79    return cpp17_input_iterator<int*>(globalBuff);80  }81  constexpr sentinel end() const { return {}; }82};83 84struct Cpp20InputRange {85  struct sentinel {86    friend constexpr bool operator==(sentinel, const cpp20_input_iterator<int*> &iter) { return base(iter) == globalBuff + 8; }87    friend constexpr std::ptrdiff_t operator-(sentinel, const cpp20_input_iterator<int*>&) { return -8; }88  };89 90  constexpr cpp20_input_iterator<int*> begin() const {91    return cpp20_input_iterator<int*>(globalBuff);92  }93  constexpr sentinel end() const { return {}; }94};95 96template<>97inline constexpr bool std::ranges::enable_borrowed_range<Cpp20InputRange> = true;98 99template<class R>100concept EmptyIsInvocable = requires (std::ranges::ref_view<R> view) { view.empty(); };101 102template<class R>103concept SizeIsInvocable = requires (std::ranges::ref_view<R> view) { view.size(); };104 105template<class R>106concept DataIsInvocable = requires (std::ranges::ref_view<R> view) { view.data(); };107 108// Testing ctad.109static_assert(std::same_as<decltype(std::ranges::ref_view(std::declval<Range&>())),110              std::ranges::ref_view<Range>>);111 112constexpr bool test() {113  {114    // ref_view::base115    Range range;116    std::ranges::ref_view<Range> view{range};117    assert(view.begin() == globalBuff);118    view.base() = Range{2};119    assert(view.begin() == globalBuff + 2);120  }121 122  {123    // ref_view::begin124    Range range1;125    std::ranges::ref_view<Range> view1 = range1;126    assert(view1.begin() == globalBuff);127 128    ForwardRange range2;129    std::ranges::ref_view<ForwardRange> view2 = range2;130    assert(base(view2.begin()) == globalBuff);131 132    Cpp17InputRange range3;133    std::ranges::ref_view<Cpp17InputRange> view3 = range3;134    assert(base(view3.begin()) == globalBuff);135 136    Cpp20InputRange range4;137    std::ranges::ref_view<Cpp20InputRange> view4 = range4;138    assert(base(view4.begin()) == globalBuff);139  }140 141  {142    // ref_view::end143    Range range1;144    std::ranges::ref_view<Range> view1 = range1;145    assert(view1.end() == globalBuff + 8);146 147    ForwardRange range2;148    std::ranges::ref_view<ForwardRange> view2 = range2;149    assert(base(view2.end()) == globalBuff + 8);150 151    Cpp17InputRange range3;152    std::ranges::ref_view<Cpp17InputRange> view3 = range3;153    assert(view3.end() == cpp17_input_iterator(globalBuff + 8));154 155    Cpp20InputRange range4;156    std::ranges::ref_view<Cpp20InputRange> view4 = range4;157    assert(view4.end() == cpp20_input_iterator(globalBuff + 8));158  }159 160  {161    // ref_view::empty162    Range range{8};163    std::ranges::ref_view<Range> view1 = range;164    assert(view1.empty());165 166    ForwardRange range2;167    std::ranges::ref_view<ForwardRange> view2 = range2;168    assert(!view2.empty());169 170    static_assert(!EmptyIsInvocable<Cpp17InputRange>);171    static_assert(!EmptyIsInvocable<Cpp20InputRange>);172  }173 174  {175    // ref_view::size176    Range range1{8};177    std::ranges::ref_view<Range> view1 = range1;178    assert(view1.size() == 0);179 180    Range range2{2};181    std::ranges::ref_view<Range> view2 = range2;182    assert(view2.size() == 6);183 184    static_assert(!SizeIsInvocable<ForwardRange>);185  }186 187  {188    // ref_view::data189    Range range1;190    std::ranges::ref_view<Range> view1 = range1;191    assert(view1.data() == globalBuff);192 193    Range range2{2};194    std::ranges::ref_view<Range> view2 = range2;195    assert(view2.data() == globalBuff + 2);196 197    static_assert(!DataIsInvocable<ForwardRange>);198  }199 200  return true;201}202 203int main(int, char**) {204  test();205  static_assert(test());206 207  return 0;208}209