SeqAn3  3.2.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-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 <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 
104  friend derived_type;
105 
106 public:
110  // a default constructor is not provided, however the constructor below might be one.
111  constexpr adaptor_base(adaptor_base const &) noexcept = default;
112  constexpr adaptor_base(adaptor_base &&) noexcept = default;
113  constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
114  constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
115  ~adaptor_base() noexcept = default;
116 
118  constexpr adaptor_base(stored_args_ts... args) noexcept(noexcept(std::tuple<stored_args_ts...>{
119  std::forward<stored_args_ts>(args)...})) :
120  arguments{std::forward<stored_args_ts>(args)...}
121  {}
123 
125  template <std::ranges::input_range urng_t>
126  constexpr auto operator()(urng_t && urange) const &
127  {
128  return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
129  }
130 
132  template <std::ranges::input_range urng_t>
133  constexpr auto operator()(urng_t && urange) &&
134  {
135  return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
136  std::make_index_sequence<sizeof...(stored_args_ts)>{});
137  }
138 
150  template <typename arg_t>
151  constexpr friend auto operator|(arg_t && arg, derived_type const & me)
152  {
153  if constexpr (std::ranges::input_range<arg_t>)
154  return me(std::forward<arg_t>(arg));
155  else
156  return combined_adaptor{std::forward<arg_t>(arg), me};
157  }
158 
160  template <typename arg_t>
161  constexpr friend auto operator|(arg_t && arg, derived_type && me)
162  {
163  if constexpr (std::ranges::input_range<arg_t>)
164  return std::move(me)(std::forward<arg_t>(arg));
165  else
166  return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
167  }
168 
185  template <typename arg_t>
186  constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
187  {
188  return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
189  }
190 
192  template <typename arg_t>
193  constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
194  {
195  return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
196  }
197 };
198 
199 // ============================================================================
200 // combined_adaptor
201 // ============================================================================
202 
213 template <typename left_adaptor_t, typename right_adaptor_t>
214 class combined_adaptor :
215  public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>
216 {
217 private:
219  using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>;
220 
222  friend base_type;
223 
225  template <std::ranges::input_range urng_t, typename left_adaptor_t_, typename right_adaptor_t_>
226  static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
227  {
228  return std::forward<urng_t>(urange) | std::forward<left_adaptor_t_>(left_adaptor)
229  | std::forward<right_adaptor_t_>(right_adaptor);
230  }
231 
232 public:
236  constexpr combined_adaptor() = default;
237  constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
238  constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
239  constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
240  constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
241  ~combined_adaptor() noexcept = default;
242 
244  using base_type::base_type;
245 
247  constexpr combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
248  base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
249  {}
251 };
252 
253 } // namespace seqan3::detail
T forward(T... args)
requires std::common_with< typename std::remove_reference_t< validator1_type >::option_value_type, typename std::remove_reference_t< validator2_type >::option_value_type > auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1124
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
The <ranges> header from C++20's standard library.