SeqAn3  3.1.0-rc.1
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 
13 #pragma once
14 
15 #include <seqan3/std/ranges>
16 #include <tuple>
17 
18 #include <seqan3/core/platform.hpp>
19 
20 namespace seqan3::detail
21 {
22 
23 // ============================================================================
24 // forwards
25 // ============================================================================
26 
27 template <typename left_adaptor_t, typename right_adaptor_t>
28 class combined_adaptor;
29 
30 // ============================================================================
31 // adaptor_base
32 // ============================================================================
33 
75 template <typename derived_type, typename ...stored_args_ts>
76 class adaptor_base
77 {
78 private:
80  std::tuple<stored_args_ts...> arguments;
81 
83  template <typename urng_t, size_t... Is>
84  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) const &
85  {
86  // std::get returns lvalue-reference to value, but we need to copy the values
87  // so that the view does not depend on the functor
88  return static_cast<derived_type const &>(*this).impl(
89  std::forward<urng_t>(urange),
90  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(arguments))...);
91  }
92 
94  template <typename urng_t, size_t... Is>
95  constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) &&
96  {
97  // move out values, because we don't need them anymore (*this is temporary)
98  return static_cast<derived_type &&>(*this).impl(
99  std::forward<urng_t>(urange),
100  std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(std::move(arguments)))...);
101  }
102 
103 
105  friend derived_type;
106 
107 public:
111  // a default constructor is not provided, however the constructor below might be one.
112  constexpr adaptor_base(adaptor_base const &) noexcept = default;
113  constexpr adaptor_base(adaptor_base &&) noexcept = default;
114  constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
115  constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
116  ~adaptor_base() noexcept = default;
117 
119  constexpr adaptor_base(stored_args_ts ... args)
120  noexcept(noexcept(std::tuple<stored_args_ts...>{std::forward<stored_args_ts>(args)...})) :
121  arguments{std::forward<stored_args_ts>(args)...}
122  {}
124 
126  template <std::ranges::input_range urng_t>
127  constexpr auto operator()(urng_t && urange) const &
128  {
129  return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
130  }
131 
133  template <std::ranges::input_range urng_t>
134  constexpr auto operator()(urng_t && urange) &&
135  {
136  return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
137  std::make_index_sequence<sizeof...(stored_args_ts)>{});
138  }
139 
151  template <typename arg_t>
152  constexpr friend auto operator|(arg_t && arg, derived_type const & me)
153  {
154  if constexpr (std::ranges::input_range<arg_t>)
155  return me(std::forward<arg_t>(arg));
156  else
157  return combined_adaptor{std::forward<arg_t>(arg), me};
158  }
159 
161  template <typename arg_t>
162  constexpr friend auto operator|(arg_t && arg, derived_type && me)
163  {
164  if constexpr (std::ranges::input_range<arg_t>)
165  return std::move(me)(std::forward<arg_t>(arg));
166  else
167  return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
168  }
169 
186  template <typename arg_t>
187  constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
188  {
189  return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
190  }
191 
193  template <typename arg_t>
194  constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
195  {
196  return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
197  }
198 };
199 
200 // ============================================================================
201 // combined_adaptor
202 // ============================================================================
203 
214 template <typename left_adaptor_t, typename right_adaptor_t>
215 class combined_adaptor :
216  public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
217  left_adaptor_t,
218  right_adaptor_t>
219 {
220 private:
222  using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
223  left_adaptor_t,
224  right_adaptor_t>;
225 
227  friend base_type;
228 
230  template <std::ranges::input_range urng_t,
231  typename left_adaptor_t_,
232  typename right_adaptor_t_>
233  static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
234  {
235  return std::forward<urng_t>(urange)
236  | std::forward<left_adaptor_t_>(left_adaptor)
237  | std::forward<right_adaptor_t_>(right_adaptor);
238  }
239 
240 public:
244  constexpr combined_adaptor() = default;
245  constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
246  constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
247  constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
248  constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
249  ~combined_adaptor() noexcept = default;
250 
252  using base_type::base_type;
253 
255  constexpr combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
256  base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
257  {}
259 };
260 
261 } // namespace seqan3::detail
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1096
SeqAn specific customisations in the standard namespace.
Definition: affine_cell_proxy.hpp:438
Provides platform and dependency checks.
Adaptations of concepts from the Ranges TS.