SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
single_pass_input.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
15 #include <seqan3/std/concepts>
16 #include <seqan3/std/iterator>
17 #include <seqan3/std/ranges>
18 
20 
21 //-----------------------------------------------------------------------------
22 // Implementation of single pass input view.
23 //-----------------------------------------------------------------------------
24 
25 namespace seqan3::detail
26 {
27 
29 template <typename view_t>
30 class basic_iterator;
31 
38 template <std::ranges::view urng_t>
39 class single_pass_input_view : public std::ranges::view_interface<single_pass_input_view<urng_t>>
40 {
42 private:
43 
45  using urng_iterator_type = std::ranges::iterator_t<urng_t>;
46 
48  template <typename view_t>
49  friend class basic_iterator;
50 
52  struct state
53  {
55  urng_t urng;
57  urng_iterator_type cached_urng_iter = std::ranges::begin(urng);
58  };
59 
61  std::shared_ptr<state> state_ptr{};
62 
67  using iterator = basic_iterator<single_pass_input_view>;
69  using sentinel = std::ranges::sentinel_t<urng_t>;
70  //\}
71 
72 public:
78  constexpr single_pass_input_view() = default;
80  constexpr single_pass_input_view(single_pass_input_view const &) = default;
82  constexpr single_pass_input_view(single_pass_input_view &&) = default;
84  constexpr single_pass_input_view & operator=(single_pass_input_view const &) = default;
86  constexpr single_pass_input_view & operator=(single_pass_input_view &&) = default;
88  ~single_pass_input_view() = default;
89 
91  explicit single_pass_input_view(urng_t _urng) :
92  state_ptr{new state{std::move(_urng)}}
93  {}
94 
96  template <typename other_urng_t>
98  requires (!std::same_as<std::remove_cvref_t<other_urng_t>, single_pass_input_view> &&
99  std::ranges::viewable_range<other_urng_t> && // Must come after self type check to avoid conflicts with the move constructor.
100  std::constructible_from<urng_t, std::ranges::ref_view<std::remove_reference_t<other_urng_t>>>)
102  explicit single_pass_input_view(other_urng_t && _urng) :
103  single_pass_input_view{std::views::all(_urng)}
104  {}
106 
117  iterator begin()
118  {
119  return {*this};
120  }
121 
123  iterator begin() const = delete;
124 
126  sentinel end()
127  {
128  return {std::ranges::end(state_ptr->urng)};
129  }
130 
132  sentinel end() const = delete;
134 };
135 
142 template <std::ranges::viewable_range urng_t>
143 single_pass_input_view(urng_t &&) ->
144  single_pass_input_view<std::views::all_t<urng_t>>;
146 } // seqan3::detail
147 
148 //-----------------------------------------------------------------------------
149 // Iterator for single pass input view.
150 //-----------------------------------------------------------------------------
151 
152 namespace seqan3::detail
153 {
161 template <typename view_type>
162 class basic_iterator<single_pass_input_view<view_type>>
163 {
165  using base_iterator_type = typename single_pass_input_view<view_type>::urng_iterator_type;
167  using sentinel_type = typename single_pass_input_view<view_type>::sentinel;
168 
170  single_pass_input_view<view_type> * view_ptr{};
171 
173  template <typename input_view_type>
174  friend class basic_iterator;
175 
177  static_assert(std::sentinel_for<sentinel_type, base_iterator_type>);
178 
179 public:
180 
185  using difference_type = std::iter_difference_t<base_iterator_type>;
187  using value_type = std::iter_value_t<base_iterator_type>;
189  using pointer = detail::iter_pointer_t<base_iterator_type>;
193  using iterator_category = std::input_iterator_tag;
195 
200  basic_iterator() = default;
202  constexpr basic_iterator(basic_iterator const & rhs) = default;
204  constexpr basic_iterator(basic_iterator && rhs) = default;
206  constexpr basic_iterator & operator=(basic_iterator const & rhs) = default;
208  constexpr basic_iterator & operator=(basic_iterator && rhs) = default;
210  ~basic_iterator() = default;
211 
213  basic_iterator(single_pass_input_view<view_type> & view) noexcept : view_ptr{&view}
214  {}
216 
221  reference operator*() const noexcept
222  {
223  return *cached();
224  }
225 
227  pointer operator->() const noexcept
229  requires (!std::is_void_v<pointer>)
231  {
232  return std::addressof(*cached());
233  }
235 
240  basic_iterator & operator++() noexcept
241  {
242  ++cached();
243  return *this;
244  }
245 
247  auto operator++(int) noexcept
248  {
249  if constexpr (std::output_iterator<base_iterator_type, reference> &&
250  std::copy_constructible<base_iterator_type>)
251  {
252  basic_iterator tmp{*this};
253  ++(*this);
254  return tmp;
255  }
256  else
257  {
258  ++(*this);
259  }
260  }
262 
267  constexpr bool operator==(sentinel_type const & s) const noexcept
268  {
269  return cached() == s;
270  }
271 
273  friend constexpr bool
274  operator==(sentinel_type const & s, basic_iterator const & rhs) noexcept
275  {
276  return rhs == s;
277  }
278 
280  constexpr bool operator!=(sentinel_type const & rhs) const noexcept
281  {
282  return !(*this == rhs);
283  }
284 
286  friend constexpr bool
287  operator!=(sentinel_type const & s, basic_iterator const & rhs) noexcept
288  {
289  return rhs != s;
290  }
292 
293 protected:
296  base_iterator_type & cached() const noexcept
297  {
298  assert(view_ptr != nullptr);
299  assert(view_ptr->state_ptr != nullptr);
300  return view_ptr->state_ptr->cached_urng_iter;
301  }
302 };
303 } // seqan3::detail
304 
305 //-----------------------------------------------------------------------------
306 // View shortcut for functor.
307 //-----------------------------------------------------------------------------
308 
310 namespace seqan3::views
311 {
363 inline constexpr auto single_pass_input = detail::adaptor_for_view_without_args<detail::single_pass_input_view>{};
364 
366 } // namespace seqan3::views
T addressof(T... args)
T begin(T... args)
The Concepts library.
T end(T... args)
constexpr auto single_pass_input
A view adapter that decays most of the range properties and adds single pass behavior.
Definition: single_pass_input.hpp:363
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
Provides C++20 additions to the <iterator> header.
The SeqAn namespace for views.
Definition: char_to.hpp:22
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Adaptations of concepts from the Ranges TS.