brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 529a609 Raw
152 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 end()12// constexpr auto end() const13 14#include <array>15#include <cassert>16#include <ranges>17 18#include "test_iterators.h"19 20struct DefaultConstructibleView : std::ranges::view_base {21  int* begin() const;22  int* end() const;23};24 25struct CVCallView : std::ranges::view_base {26  mutable bool const_called = false;27  mutable int i[1];28  constexpr int* begin() {29    const_called = false;30    return i;31  }32 33  constexpr int* begin() const {34    const_called = true;35    return i;36  }37 38  constexpr int* end() {39    const_called = false;40    return i + 1;41  }42 43  constexpr int* end() const {44    const_called = true;45    return i + 1;46  }47};48 49struct NonConstCommonRange : std::ranges::view_base {50  int* begin();51  int* end();52 53  int* begin() const;54  sentinel_wrapper<int*> end() const;55};56 57struct NonConstView : std::ranges::view_base {58  int* begin();59  int* end();60};61 62template <class T>63concept HasEnd = requires(T t) { t.end(); };64 65static_assert(HasEnd<std::ranges::as_rvalue_view<DefaultConstructibleView>>);66static_assert(HasEnd<const std::ranges::as_rvalue_view<DefaultConstructibleView>>);67static_assert(HasEnd<std::ranges::as_rvalue_view<NonConstView>>);68static_assert(!HasEnd<const std::ranges::as_rvalue_view<NonConstView>>);69 70static_assert(std::is_same_v<decltype(std::declval<std::ranges::as_rvalue_view<DefaultConstructibleView>>().end()),71                             std::move_iterator<int*>>);72static_assert(std::is_same_v<decltype(std::declval<const std::ranges::as_rvalue_view<NonConstCommonRange>>().end()),73                             std::move_sentinel<sentinel_wrapper<int*>>>);74 75template <class Iter, class Sent, bool is_common>76constexpr void test_range() {77  using Expected = std::conditional_t<is_common, std::move_iterator<Sent>, std::move_sentinel<Sent>>;78  int a[]        = {1, 2};79  std::ranges::subrange range(Iter(std::begin(a)), Sent(Iter(std::end(a))));80  std::ranges::as_rvalue_view view(std::move(range));81  std::same_as<Expected> decltype(auto) iter = view.end();82  assert(base(base(iter.base())) == std::end(a));83}84 85template <class Iter, class Sent>86class WrapRange {87  Iter iter_;88  Sent sent_;89 90public:91  constexpr WrapRange(Iter iter, Sent sent) : iter_(std::move(iter)), sent_(std::move(sent)) {}92 93  constexpr Iter begin() const { return iter_; }94  constexpr Sent end() const { return sent_; }95};96 97template <class Iter, class Sent>98WrapRange(Iter, Sent) -> WrapRange<Iter, Sent>;99 100template <class Iter, class Sent, bool is_common>101constexpr void test_const_range() {102  using Expected = std::conditional_t<is_common, std::move_iterator<Sent>, std::move_sentinel<Sent>>;103  int a[]        = {1, 2};104  auto range = WrapRange{Iter(a), Sent(Iter(a + 2))};105  const std::ranges::as_rvalue_view view(std::move(range));106  std::same_as<Expected> decltype(auto) iter = view.end();107  assert(base(base(iter.base())) == std::end(a));108}109 110struct move_iterator_view : std::ranges::view_base {111  constexpr std::move_iterator<int*> begin() const { return {}; }112  constexpr std::move_iterator<int*> end() const { return {}; }113};114 115constexpr bool test() {116  test_range<cpp17_input_iterator<int*>, sentinel_wrapper<cpp17_input_iterator<int*>>, false>();117  test_range<cpp17_input_iterator<int*>, sized_sentinel<cpp17_input_iterator<int*>>, false>();118  test_range<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>, false>();119  test_range<cpp20_input_iterator<int*>, sized_sentinel<cpp20_input_iterator<int*>>, false>();120 121  types::for_each(types::forward_iterator_list<int*>{}, []<class Iter> {122    test_range<Iter, Iter, true>();123    test_range<Iter, sentinel_wrapper<Iter>, false>();124    test_range<Iter, sized_sentinel<Iter>, false>();125  });126 127  {128    std::ranges::as_rvalue_view view(CVCallView{});129    (void)view.end();130    assert(view.base().const_called);131  }132 133  { // check that with a std::move_iterator begin() doesn't return move_iterator<move_iterator<T>>134    std::ranges::as_rvalue_view view{move_iterator_view{}};135    std::same_as<std::move_iterator<int*>> decltype(auto) it = view.end();136    assert(it == std::move_iterator<int*>{});137  }138 139  return true;140}141 142int main(int, char**) {143  test();144 145// gcc cannot have mutable member in constant expression146#if !defined(TEST_COMPILER_GCC)147  static_assert(test());148#endif149 150  return 0;151}152