SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
detail.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 
14 #pragma once
15 
16 #include <tuple>
17 
20 #include <seqan3/std/ranges>
21 
22 namespace seqan3::detail
23 {
24 
25 // ============================================================================
26 // forwards
27 // ============================================================================
28 
29 template <typename left_adaptor_t, typename right_adaptor_t>
30 class combined_adaptor;
31 
32 // ============================================================================
33 // adaptor_base
34 // ============================================================================
35 
77 template <typename derived_type, typename ...stored_args_ts>
78 class adaptor_base
79 {
80 private:
82  std::tuple<stored_args_ts...> arguments;
83 
85  template <typename urng_t, size_t... Is>
86  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) const &
87  {
88  // std::get returns lvalue-reference to value, but we need to copy the values
89  // so that the view does not depend on the functor
90  return static_cast<derived_type const &>(*this).impl(
91  std::forward<urng_t>(urange),
92  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(arguments))...);
93  }
94 
96  template <typename urng_t, size_t... Is>
97  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) &&
98  {
99  // move out values, because we don't need them anymore (*this is temporary)
100  return static_cast<derived_type &&>(*this).impl(
101  std::forward<urng_t>(urange),
102  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(std::move(arguments)))...);
103  }
104 
105 
107  friend derived_type;
108 
109 public:
113  // a default constructor is not provided, however the constructor below might be one.
114  constexpr adaptor_base(adaptor_base const &) noexcept = default;
115  constexpr adaptor_base(adaptor_base &&) noexcept = default;
116  constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
117  constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
118  ~adaptor_base() noexcept = default;
119 
121  constexpr adaptor_base(stored_args_ts ... args)
122  noexcept(noexcept(std::tuple<stored_args_ts...>{std::forward<stored_args_ts>(args)...})) :
123  arguments{std::forward<stored_args_ts>(args)...}
124  {}
126 
128  template <std::ranges::input_range urng_t>
129  constexpr auto operator()(urng_t && urange) const &
130  {
131  return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
132  }
133 
135  template <std::ranges::input_range urng_t>
136  constexpr auto operator()(urng_t && urange) &&
137  {
138  return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
139  std::make_index_sequence<sizeof...(stored_args_ts)>{});
140  }
141 
153  template <typename arg_t>
154  constexpr friend auto operator|(arg_t && arg, derived_type const & me)
155  {
156  if constexpr (std::ranges::input_range<arg_t>)
157  return me(std::forward<arg_t>(arg));
158  else
159  return combined_adaptor{std::forward<arg_t>(arg), me};
160  }
161 
163  template <typename arg_t>
164  constexpr friend auto operator|(arg_t && arg, derived_type && me)
165  {
166  if constexpr (std::ranges::input_range<arg_t>)
167  return std::move(me)(std::forward<arg_t>(arg));
168  else
169  return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
170  }
171 
188  template <typename arg_t>
189  constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
190  {
191  return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
192  }
193 
195  template <typename arg_t>
196  constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
197  {
198  return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
199  }
200 };
201 
202 // ============================================================================
203 // combined_adaptor
204 // ============================================================================
205 
216 template <typename left_adaptor_t, typename right_adaptor_t>
217 class combined_adaptor :
218  public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
219  left_adaptor_t,
220  right_adaptor_t>
221 {
222 private:
224  using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
225  left_adaptor_t,
226  right_adaptor_t>;
227 
229  friend base_type;
230 
232  template <std::ranges::input_range urng_t,
233  typename left_adaptor_t_,
234  typename right_adaptor_t_>
235  static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
236  {
237  return std::forward<urng_t>(urange)
238  | std::forward<left_adaptor_t_>(left_adaptor)
239  | std::forward<right_adaptor_t_>(right_adaptor);
240  }
241 
242 public:
246  constexpr combined_adaptor() = default;
247  constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
248  constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
249  constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
250  constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
251  ~combined_adaptor() noexcept = default;
252 
254  using base_type::base_type;
256 
258  combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
259  base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
260  {}
261 };
262 
263 // ============================================================================
264 // adaptor_for_view_without_args
265 // ============================================================================
266 
290 template <template <typename, typename ...> typename view_type>
291 class adaptor_for_view_without_args : public adaptor_base<adaptor_for_view_without_args<view_type>>
292 {
293 private:
295  using base_type = adaptor_base<adaptor_for_view_without_args<view_type>>;
296 
298  friend base_type;
299 
306  template <typename ...arg_types>
307  static auto impl(arg_types && ... args)
308  {
309  return view_type{std::forward<arg_types>(args)...};
310  }
311 
312 public:
316  constexpr adaptor_for_view_without_args() = default;
319  constexpr adaptor_for_view_without_args(adaptor_for_view_without_args const &) noexcept = default;
321  constexpr adaptor_for_view_without_args(adaptor_for_view_without_args &&) noexcept = default;
323  constexpr adaptor_for_view_without_args & operator=(adaptor_for_view_without_args const &) noexcept = default;
325  constexpr adaptor_for_view_without_args & operator=(adaptor_for_view_without_args &&) noexcept = default;
327  ~adaptor_for_view_without_args() noexcept = default;
328 
330  using base_type::base_type;
332 };
333 
334 // ============================================================================
335 // adaptor_from_functor
336 // ============================================================================
337 
368 template <typename functor_type, typename ...stored_args_ts>
369 class adaptor_from_functor :
370  public adaptor_base<adaptor_from_functor<functor_type, stored_args_ts...>, stored_args_ts...>
371 {
372 private:
374  using base_type = adaptor_base<adaptor_from_functor<functor_type, stored_args_ts...>, stored_args_ts...>;
375 
377  friend base_type;
378 
380  functor_type fun;
381 
389  template <std::ranges::input_range urng_t>
390  constexpr auto impl(urng_t && urange, stored_args_ts ... args) const
391  {
392  return fun(std::forward<urng_t>(urange), std::forward<stored_args_ts>(args)...);
393  }
394 
395 public:
399  constexpr adaptor_from_functor() = default;
400  constexpr adaptor_from_functor(adaptor_from_functor const &) noexcept = default;
401  constexpr adaptor_from_functor(adaptor_from_functor &&) noexcept = default;
402  constexpr adaptor_from_functor & operator=(adaptor_from_functor const &) noexcept = default;
403  constexpr adaptor_from_functor & operator=(adaptor_from_functor &&) noexcept = default;
404  ~adaptor_from_functor() noexcept = default;
405 
407  constexpr adaptor_from_functor(functor_type f, stored_args_ts ... args) :
408  base_type{std::forward<stored_args_ts>(args)...}, fun{std::move(f)}
409  {}
411 };
412 
413 } // namespace seqan3::detail
std::index_sequence
basic.hpp
Provides various type traits on generic types.
seqan3::views::move
const auto move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
tuple
seqan3::operator|
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1023
range.hpp
Provides various transformation traits used by the range module.
ranges
Adaptations of concepts from the Ranges TS.
std
SeqAn specific customisations in the standard namespace.