brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · db846b2 Raw
115 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++17, c++2010 11// constexpr auto begin()12// constexpr auto begin() const13 14#include <array>15#include <cassert>16#include <concepts>17#include <ranges>18 19#include "test_iterators.h"20 21struct SimpleView : std::ranges::view_base {22  int* begin() const;23  int* end() const;24};25 26struct NonSimpleView : std::ranges::view_base {27  char* begin();28  char* end();29  int* begin() const;30  int* end() const;31};32 33struct NonConstView : std::ranges::view_base {34  char* begin();35  char* end();36};37 38template <class T>39concept HasBegin = requires(T t) { t.begin(); };40 41static_assert(HasBegin<std::ranges::as_rvalue_view<SimpleView>>);42static_assert(HasBegin<const std::ranges::as_rvalue_view<SimpleView>>);43static_assert(HasBegin<std::ranges::as_rvalue_view<NonSimpleView>>);44static_assert(HasBegin<const std::ranges::as_rvalue_view<NonSimpleView>>);45static_assert(HasBegin<std::ranges::as_rvalue_view<NonConstView>>);46static_assert(!HasBegin<const std::ranges::as_rvalue_view<NonConstView>>);47 48template <class Iter, class Sent>49constexpr void test_range() {50  int a[] = {1, 2};51  std::ranges::subrange range(Iter(std::begin(a)), Sent(Iter(std::end(a))));52  std::ranges::as_rvalue_view view(std::move(range));53  std::same_as<std::move_iterator<Iter>> decltype(auto) iter = view.begin();54  assert(base(iter.base()) == std::begin(a));55}56 57template <class Iter, class Sent>58class WrapRange {59  Iter iter_;60  Sent sent_;61 62public:63  constexpr WrapRange(Iter iter, Sent sent) : iter_(std::move(iter)), sent_(std::move(sent)) {}64 65  constexpr Iter begin() const { return iter_; }66  constexpr Sent end() const { return sent_; }67};68 69template <class Iter, class Sent>70WrapRange(Iter, Sent) -> WrapRange<Iter, Sent>;71 72template <class Iter, class Sent>73constexpr void test_const_range() {74  int a[]    = {1, 2};75  auto range = WrapRange{Iter(a), Sent(Iter(a + 2))};76  const std::ranges::as_rvalue_view view(std::views::all(range));77  std::same_as<std::move_iterator<Iter>> decltype(auto) iter = view.begin();78  assert(base(iter.base()) == std::begin(a));79}80 81struct move_iterator_view : std::ranges::view_base {82  constexpr std::move_iterator<int*> begin() const { return {}; }83  constexpr std::move_iterator<int*> end() const { return {}; }84};85 86constexpr bool test() {87  types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iter> {88    if constexpr (std::sentinel_for<Iter, Iter>)89      test_range<Iter, Iter>();90    test_range<Iter, sentinel_wrapper<Iter>>();91    test_range<Iter, sized_sentinel<Iter>>();92  });93 94  types::for_each(types::forward_iterator_list<const int*>{}, []<class Iter> {95    test_const_range<Iter, Iter>();96    test_const_range<Iter, sentinel_wrapper<Iter>>();97    test_const_range<Iter, sized_sentinel<Iter>>();98  });99 100  { // check that with a std::move_iterator begin() doesn't return move_iterator<move_iterator<T>>101    std::ranges::as_rvalue_view view{move_iterator_view{}};102    std::same_as<std::move_iterator<int*>> decltype(auto) it = view.begin();103    assert(it == std::move_iterator<int*>{});104  }105 106  return true;107}108 109int main(int, char**) {110  test();111  static_assert(test());112 113  return 0;114}115