brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · f9d2b3e Raw
162 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// friend constexpr decltype(auto) iter_move(const inner-iterator& i)12//   noexcept(noexcept(ranges::iter_move(i.i_.<current>)));13 14#include <iterator>15 16#include <cassert>17#include <type_traits>18#include <utility>19#include "../types.h"20 21namespace adl {22 23template <bool IsNoexcept = false>24struct MaybeNoexceptIterator {25  using value_type = int;26  using difference_type = std::ptrdiff_t;27 28  value_type* ptr_ = nullptr;29  int* iter_move_invocations_ = nullptr;30 31  constexpr MaybeNoexceptIterator() = default;32  constexpr explicit MaybeNoexceptIterator(int* p, int& iter_moves) : ptr_(p), iter_move_invocations_(&iter_moves) {}33 34  constexpr value_type& operator*() const { return *ptr_; }35 36  MaybeNoexceptIterator& operator++() { ++ptr_; return *this; }37  MaybeNoexceptIterator operator++(int) {38    MaybeNoexceptIterator prev = *this;39    ++ptr_;40    return prev;41  }42 43  constexpr MaybeNoexceptIterator& operator--() { --ptr_; return *this; }44  constexpr MaybeNoexceptIterator operator--(int) {45    MaybeNoexceptIterator prev = *this;46    --ptr_;47    return prev;48  }49 50  constexpr friend value_type&& iter_move(MaybeNoexceptIterator iter) noexcept(IsNoexcept) {51    if (iter.iter_move_invocations_) {52      ++(*iter.iter_move_invocations_);53    }54    return std::move(*iter);55  }56 57  friend bool operator==(const MaybeNoexceptIterator& lhs, const MaybeNoexceptIterator& rhs) { return lhs.ptr_ == rhs.ptr_; }58};59 60template <bool IsNoexcept = false>61struct View : std::ranges::view_base {62  static constexpr int N = 3;63  int a[N] = {0, 1, 2};64  int* iter_moves = nullptr;65 66  constexpr View() = default;67  constexpr View(int& iter_move_invocations) : iter_moves(&iter_move_invocations) {68  }69 70  constexpr adl::MaybeNoexceptIterator<IsNoexcept> begin() {71    return adl::MaybeNoexceptIterator<IsNoexcept>(a, *iter_moves);72  }73  constexpr adl::MaybeNoexceptIterator<IsNoexcept> end() {74    return adl::MaybeNoexceptIterator<IsNoexcept>(a + N, *iter_moves);75  }76};77 78} // namespace adl79 80constexpr bool test() {81  // Can use `iter_move` with `inner-iterator`; `View` is a forward range.82  {83    SplitViewForward v("abc def", " ");84    auto segment = *v.begin();85 86    // Non-const iterator.87    {88      auto i = segment.begin();89      static_assert(std::same_as<decltype(iter_move(i)), const char &&>);90      assert(iter_move(i) == 'a');91    }92 93    // Const iterator.94    {95      const auto i = segment.begin();96      static_assert(std::same_as<decltype(iter_move(i)), const char &&>);97      assert(iter_move(i) == 'a');98    }99  }100 101  // Can use `iter_move` with `inner-iterator`, `View` is an input range.102  {103    SplitViewInput v("abc def", ' ');104    auto segment = *v.begin();105 106    // Non-const iterator.107    {108      auto i = segment.begin();109      static_assert(std::same_as<decltype(iter_move(i)), char &&>);110      assert(iter_move(i) == 'a');111    }112 113    // Const iterator.114    {115      const auto i = segment.begin();116      static_assert(std::same_as<decltype(iter_move(i)), char &&>);117      assert(iter_move(i) == 'a');118    }119  }120 121  // Ensure the `iter_move` customization point is being used.122  {123    int iter_move_invocations = 0;124    adl::View<> input(iter_move_invocations);125    std::ranges::lazy_split_view<adl::View<>, adl::View<>> v(input, adl::View<>());126 127    auto segment = *v.begin();128    auto i = segment.begin();129    int x = iter_move(i);130    assert(x == 0);131    assert(iter_move_invocations == 1);132  }133 134  // Check the `noexcept` specification.135  {136    {137      using ThrowingSplitView = std::ranges::lazy_split_view<adl::View<false>, adl::View<false>>;138      using ThrowingValueType = std::ranges::iterator_t<ThrowingSplitView>::value_type;139      using ThrowingIter = std::ranges::iterator_t<ThrowingValueType>;140      ASSERT_NOT_NOEXCEPT(std::ranges::iter_move(std::declval<adl::MaybeNoexceptIterator<false>>()));141      ASSERT_NOT_NOEXCEPT(iter_move(std::declval<ThrowingIter>()));142    }143 144    {145      using NoexceptSplitView = std::ranges::lazy_split_view<adl::View<true>, adl::View<true>>;146      using NoexceptValueType = std::ranges::iterator_t<NoexceptSplitView>::value_type;147      using NoexceptIter = std::ranges::iterator_t<NoexceptValueType>;148      ASSERT_NOEXCEPT(std::ranges::iter_move(std::declval<adl::MaybeNoexceptIterator<true>>()));149      ASSERT_NOEXCEPT(iter_move(std::declval<NoexceptIter>()));150    }151  }152 153  return true;154}155 156int main(int, char**) {157  test();158  static_assert(test());159 160  return 0;161}162