SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
adaptor_base.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <ranges>
13#include <tuple>
14
16
17namespace seqan3::detail
18{
19
20// ============================================================================
21// forwards
22// ============================================================================
23
24template <typename left_adaptor_t, typename right_adaptor_t>
25class combined_adaptor;
26
27// ============================================================================
28// adaptor_base
29// ============================================================================
30
72template <typename derived_type, typename... stored_args_ts>
73class adaptor_base
74{
75private:
77 std::tuple<stored_args_ts...> arguments;
78
80 template <typename urng_t, size_t... Is>
81 constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) const &
82 {
83 // std::get returns lvalue-reference to value, but we need to copy the values
84 // so that the view does not depend on the functor
85 return static_cast<derived_type const &>(*this).impl(
86 std::forward<urng_t>(urange),
87 std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(arguments))...);
88 }
89
91 template <typename urng_t, size_t... Is>
92 constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) &&
93 {
94 // move out values, because we don't need them anymore (*this is temporary)
95 return static_cast<derived_type &&>(*this).impl(
96 std::forward<urng_t>(urange),
97 std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(std::move(arguments)))...);
98 }
99
101 friend derived_type;
102
103public:
107 // a default constructor is not provided, however the constructor below might be one.
108 constexpr adaptor_base(adaptor_base const &) noexcept = default;
109 constexpr adaptor_base(adaptor_base &&) noexcept = default;
110 constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
111 constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
112 ~adaptor_base() noexcept = default;
113
115 constexpr adaptor_base(stored_args_ts... args) noexcept(noexcept(std::tuple<stored_args_ts...>{
116 std::forward<stored_args_ts>(args)...})) :
117 arguments{std::forward<stored_args_ts>(args)...}
118 {}
120
122 template <std::ranges::input_range urng_t>
123 constexpr auto operator()(urng_t && urange) const &
124 {
125 return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
126 }
127
129 template <std::ranges::input_range urng_t>
130 constexpr auto operator()(urng_t && urange) &&
131 {
132 return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
133 std::make_index_sequence<sizeof...(stored_args_ts)>{});
134 }
135
147 template <typename arg_t>
148 constexpr friend auto operator|(arg_t && arg, derived_type const & me)
149 {
150 if constexpr (std::ranges::input_range<arg_t>)
151 return me(std::forward<arg_t>(arg));
152 else
153 return combined_adaptor{std::forward<arg_t>(arg), me};
154 }
155
157 template <typename arg_t>
158 constexpr friend auto operator|(arg_t && arg, derived_type && me)
159 {
160 if constexpr (std::ranges::input_range<arg_t>)
161 return std::move(me)(std::forward<arg_t>(arg));
162 else
163 return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
164 }
165
182 template <typename arg_t>
183 constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
184 {
185 return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
186 }
187
189 template <typename arg_t>
190 constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
191 {
192 return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
193 }
194};
195
196// ============================================================================
197// combined_adaptor
198// ============================================================================
199
210template <typename left_adaptor_t, typename right_adaptor_t>
211class combined_adaptor :
212 public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>
213{
214private:
216 using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>;
217
219 friend base_type;
220
222 template <std::ranges::input_range urng_t, typename left_adaptor_t_, typename right_adaptor_t_>
223 static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
224 {
225 return std::forward<urng_t>(urange) | std::forward<left_adaptor_t_>(left_adaptor)
226 | std::forward<right_adaptor_t_>(right_adaptor);
227 }
228
229public:
233 constexpr combined_adaptor() = default;
234 constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
235 constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
236 constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
237 constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
238 ~combined_adaptor() noexcept = default;
239
241 using base_type::base_type;
242
244 constexpr combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
245 base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
246 {}
248};
249
250} // namespace seqan3::detail
T forward(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1121
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
Hide me