SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
adaptor_base.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 
14 #pragma once
15 
16 #include <seqan3/std/ranges>
17 #include <tuple>
18 
19 #include <seqan3/core/platform.hpp>
20 
21 namespace seqan3::detail
22 {
23 
24 // ============================================================================
25 // forwards
26 // ============================================================================
27 
28 template <typename left_adaptor_t, typename right_adaptor_t>
29 class combined_adaptor;
30 
31 // ============================================================================
32 // adaptor_base
33 // ============================================================================
34 
76 template <typename derived_type, typename ...stored_args_ts>
77 class adaptor_base
78 {
79 private:
81  std::tuple<stored_args_ts...> arguments;
82 
84  template <typename urng_t, size_t... Is>
85  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) const &
86  {
87  // std::get returns lvalue-reference to value, but we need to copy the values
88  // so that the view does not depend on the functor
89  return static_cast<derived_type const &>(*this).impl(
90  std::forward<urng_t>(urange),
91  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(arguments))...);
92  }
93 
95  template <typename urng_t, size_t... Is>
96  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) &&
97  {
98  // move out values, because we don't need them anymore (*this is temporary)
99  return static_cast<derived_type &&>(*this).impl(
100  std::forward<urng_t>(urange),
101  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(std::move(arguments)))...);
102  }
103 
104 
106  friend derived_type;
107 
108 public:
112  // a default constructor is not provided, however the constructor below might be one.
113  constexpr adaptor_base(adaptor_base const &) noexcept = default;
114  constexpr adaptor_base(adaptor_base &&) noexcept = default;
115  constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
116  constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
117  ~adaptor_base() noexcept = default;
118 
120  constexpr adaptor_base(stored_args_ts ... args)
121  noexcept(noexcept(std::tuple<stored_args_ts...>{std::forward<stored_args_ts>(args)...})) :
122  arguments{std::forward<stored_args_ts>(args)...}
123  {}
125 
127  template <std::ranges::input_range 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::input_range 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::input_range<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::input_range<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::input_range 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:
245  constexpr combined_adaptor() = default;
246  constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
247  constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
248  constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
249  constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
250  ~combined_adaptor() noexcept = default;
251 
253  using base_type::base_type;
254 
256  constexpr combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
257  base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
258  {}
260 };
261 
262 } // namespace seqan3::detail
T forward(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1103
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
Adaptations of concepts from the Ranges TS.