SeqAn3 3.1.0
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
19
20namespace seqan3::detail
21{
22
23// ============================================================================
24// forwards
25// ============================================================================
26
27template <typename left_adaptor_t, typename right_adaptor_t>
28class combined_adaptor;
29
30// ============================================================================
31// adaptor_base
32// ============================================================================
33
75template <typename derived_type, typename ...stored_args_ts>
76class adaptor_base
77{
78private:
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
107public:
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
214template <typename left_adaptor_t, typename right_adaptor_t>
215class combined_adaptor :
216 public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>,
217 left_adaptor_t,
218 right_adaptor_t>
219{
220private:
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
240public:
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
T forward(T... args)
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1120
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
The <ranges> header from C++20's standard library.