SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
deep.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
16 #include <seqan3/std/ranges>
17 
18 namespace seqan3::views
19 {
20 
100 template <typename underlying_adaptor_t>
101 class deep : public detail::adaptor_base<deep<underlying_adaptor_t>, underlying_adaptor_t>
102 {
103 private:
106 
108  friend base_type;
109 
110 public:
114  constexpr deep() noexcept = default;
115  constexpr deep(deep const &) noexcept = default;
116  constexpr deep(deep &&) noexcept = default;
117  constexpr deep & operator=(deep const &) noexcept = default;
118  constexpr deep & operator=(deep &&) noexcept = default;
119  ~deep() noexcept = default;
120 
121  using base_type::base_type;
123 
125 
127  using base_type::operator();
128 
136  template <std::ranges::input_range urng_t, typename underlying_adaptor_t_>
137  static constexpr auto impl(urng_t && urange, underlying_adaptor_t_ && adap)
138  {
139  // this function recursively constructs a view (moves/forwards omitted for readability):
140  // return range | std::views::transform([adap](auto && inner_range_depth1)
141  // {
142  // return inner_range_depth1 | std::views::transform([adap](auto && inner_range_depth2)
143  // {
144  // // ...
145  // return inner_range_depth_n | std::views::transform([adap](auto && inner_most_range)
146  // {
147  // return inner_most_range | adap;
148  // });
149  // // ...
150  // });
151  // });
152 
153  // Note: we avoid the (unqualified) pipe|-notation and use function notation here, to avoid problems with ADL.
154  if constexpr (std::ranges::input_range<std::ranges::range_reference_t<urng_t>>)
155  {
156  auto transform = [adaptor = std::forward<underlying_adaptor_t_>(adap)] (auto && inner_range)
157  {
158  // recursively call impl until inner most range is reached.
159  return impl(std::forward<decltype(inner_range)>(inner_range), std::forward<decltype(adaptor)>(adaptor));
160  };
161  return std::views::transform(std::forward<urng_t>(urange), std::move(transform));
162  }
163  else
164  {
165  // recursion anchor: this is the inner most range
166  return std::forward<underlying_adaptor_t_>(adap)(std::forward<urng_t>(urange));
167  }
168  }
169 
178  template <typename first_arg_t, typename ...stored_arg_types>
180  requires (!std::ranges::input_range<first_arg_t>)
182  constexpr auto operator()(first_arg_t && first, stored_arg_types && ...args) const
183  {
184  // The adaptor currently wrapped is a proto-adaptor and this function has the arguments to "complete" it.
185  // We extract the adaptor that is stored and invoke it with the given arguments.
186  // This returns an adaptor closure object.
187  auto adaptor_closure = std::get<0>(this->arguments)(std::forward<first_arg_t>(first),
188  std::forward<stored_arg_types>(args)...);
189  // Now we wrap this closure object back into a views::deep to get the deep behaviour.
190  return deep<decltype(adaptor_closure)>{std::move(adaptor_closure)};
191  }
192 
194  constexpr auto operator()() const
195  {
196  // Proto-adaptors require arguments by definition, but some support defaulting those (e.g. views::translate).
197  // This extracts the proto adaptor and invokes it without args which yields a different object, the closure
198  // with default arguments.
199  auto adaptor_closure = std::get<0>(this->arguments)();
200  // Now we wrap this closure object back into a views::deep to get the deep behaviour.
201  return deep<decltype(adaptor_closure)>{std::move(adaptor_closure)};
202  }
203 
216  template <std::ranges::input_range urng_t, typename ...stored_arg_types>
218  requires (sizeof...(stored_arg_types) > 0)
220  constexpr auto operator()(urng_t && urange, stored_arg_types && ...args) const
221  {
222  auto adaptor_closure = std::get<0>(this->arguments)(std::forward<stored_arg_types>(args)...);
223  deep<decltype(adaptor_closure)> deep_adaptor{std::move(adaptor_closure)};
224  return deep_adaptor(std::forward<urng_t>(urange));
225  }
226 };
227 
233 template <typename underlying_adaptor_t>
234 deep(underlying_adaptor_t && inner) -> deep<underlying_adaptor_t>;
235 
237 
238 } // namespace seqan3::views
CRTP-base to simplify the definition of range adaptor closure objects and similar types.
Definition: detail.hpp:79
std::tuple< stored_args_ts... > arguments
Stores the arguments.
Definition: detail.hpp:82
A wrapper type around an existing view adaptor that enables "deep view" behaviour for that view.
Definition: deep.hpp:102
deep(underlying_adaptor_t &&inner) -> deep< underlying_adaptor_t >
Template argument deduction helper that preserves lvalue references and turns rvalue references into ...
static constexpr auto impl(urng_t &&urange, underlying_adaptor_t_ &&adap)
Unwrap the internal adaptor closure object and pipe the range into it.
Definition: deep.hpp:137
constexpr auto operator()() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: deep.hpp:194
friend base_type
Befriend the base class so it can call impl().
Definition: deep.hpp:108
constexpr deep() noexcept=default
Defaulted.
T forward(T... args)
decltype(detail::transform< trait_t >(list_t{})) transform
Apply a transformation trait to every type in the list and return a seqan3::type_list of the results.
Definition: traits.hpp:434
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:70
The SeqAn namespace for views.
SeqAn specific customisations in the standard namespace.
Auxiliary header for the views submodule .
Adaptations of concepts from the Ranges TS.