SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
detail.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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  arguments{std::forward<stored_args_ts>(args)...}
123  {}
125 
127  template <std::ranges::InputRange urng_t>
128  constexpr auto operator()(urng_t && urange) const &
129  {
130  return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
131  }
132 
134  template <std::ranges::InputRange urng_t>
135  constexpr auto operator()(urng_t && urange) &&
136  {
137  return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
138  std::make_index_sequence<sizeof...(stored_args_ts)>{});
139  }
140 
152  template <typename arg_t>
153  constexpr friend auto operator|(arg_t && arg, derived_type const & me)
154  {
155  if constexpr (std::ranges::InputRange<arg_t>)
156  return me(std::forward<arg_t>(arg));
157  else
158  return combined_adaptor{std::forward<arg_t>(arg), me};
159  }
160 
162  template <typename arg_t>
163  constexpr friend auto operator|(arg_t && arg, derived_type && me)
164  {
165  if constexpr (std::ranges::InputRange<arg_t>)
166  return std::move(me)(std::forward<arg_t>(arg));
167  else
168  return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
169  }
170 
187  template <typename arg_t>
188  constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
189  {
190  return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
191  }
192 
194  template <typename arg_t>
195  constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
196  {
197  return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
198  }
199 };
200 
201 // ============================================================================
202 // combined_adaptor
203 // ============================================================================
204 
215 template <typename left_adaptor_t, typename right_adaptor_t>
216 class combined_adaptor :
217  public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
218  left_adaptor_t,
219  right_adaptor_t>
220 {
221 private:
223  using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
224  left_adaptor_t,
225  right_adaptor_t>;
226 
228  friend base_type;
229 
231  template <std::ranges::InputRange urng_t,
232  typename left_adaptor_t_,
233  typename right_adaptor_t_>
234  static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
235  {
236  return std::forward<urng_t>(urange)
237  | std::forward<left_adaptor_t_>(left_adaptor)
238  | std::forward<right_adaptor_t_>(right_adaptor);
239  }
240 
241 public:
243  using base_type::base_type;
244 
246  combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
247  base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
248  {}
249 };
250 
251 // ============================================================================
252 // adaptor_for_view_without_args
253 // ============================================================================
254 
278 template <template <typename, typename...> typename view_type>
279 class adaptor_for_view_without_args : public adaptor_base<adaptor_for_view_without_args<view_type>>
280 {
281 private:
283  using base_type = adaptor_base<adaptor_for_view_without_args<view_type>>;
284 
286  friend base_type;
287 
294  template <typename ... arg_types>
295  static auto impl(arg_types && ... args)
296  {
297  return view_type{std::forward<arg_types>(args)...};
298  }
299 
300 public:
302  using base_type::base_type;
303 };
304 
305 // ============================================================================
306 // adaptor_from_functor
307 // ============================================================================
308 
340 template <typename functor_type, typename ... stored_args_ts>
341 class adaptor_from_functor :
342  public adaptor_base<adaptor_from_functor<functor_type, stored_args_ts...>, stored_args_ts...>
343 {
344 private:
346  using base_type = adaptor_base<adaptor_from_functor<functor_type, stored_args_ts...>, stored_args_ts...>;
347 
349  friend base_type;
350 
352  functor_type fun;
353 
361  template <std::ranges::InputRange urng_t>
362  constexpr auto impl(urng_t && urange, stored_args_ts ... args) const
363  {
364  return fun(std::forward<urng_t>(urange), std::forward<stored_args_ts>(args)...);
365  }
366 
367 public:
369  constexpr adaptor_from_functor(functor_type f, stored_args_ts ... args) :
370  base_type{std::forward<stored_args_ts>(args)...}, fun{std::move(f)}
371  {}
372 };
373 
374 } // namespace seqan3::detail
Adaptations of concepts from the Ranges TS.
Definition: aligned_sequence_concept.hpp:35
Specifies requirements of a Range type for which begin returns a type that models std::InputIterator...
Provides various type traits on generic types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:889
Provides various transformation traits used by the range module.