SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
configuration.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/concepts>
16
23
24namespace seqan3
25{
26
27// ----------------------------------------------------------------------------
28// configuration
29// ----------------------------------------------------------------------------
30
43template <detail::config_element ... configs_t>
44class configuration : public std::tuple<configs_t...>
45{
47 template <detail::config_element ... _configs_t>
48 friend class configuration;
49
50public:
53 using base_type = std::tuple<configs_t...>;
54
56
59 constexpr configuration() = default;
60 constexpr configuration(configuration const &) = default;
61 constexpr configuration(configuration &&) = default;
62 constexpr configuration & operator=(configuration const &) = default;
63 constexpr configuration & operator=(configuration &&) = default;
64 ~configuration() = default;
65
71 template <typename config_element_t>
73 requires (!std::same_as<std::remove_cvref_t<config_element_t>, configuration>) &&
74 detail::config_element<std::remove_cvref_t<config_element_t>>
76 constexpr configuration(config_element_t && config_element) :
77 base_type{std::forward<config_element_t>(config_element)}
78 {}
80
86 constexpr size_t size() const noexcept
87 {
88 return std::tuple_size_v<base_type>;
89 }
90
121 template <typename alternative_t>
122 constexpr decltype(auto) get_or(alternative_t && alternative) & noexcept
123 {
124 return get_or_impl(*this, alternative, std::forward<alternative_t>(alternative));
125 }
126
128 template <typename alternative_t>
129 constexpr decltype(auto) get_or(alternative_t && alternative) const & noexcept
130 {
131 return get_or_impl(*this, alternative, std::forward<alternative_t>(alternative));
132 }
133
135 template <typename alternative_t>
136 constexpr decltype(auto) get_or(alternative_t && alternative) && noexcept
137 {
138 return get_or_impl(std::move(*this), alternative, std::forward<alternative_t>(alternative));
139 }
140
142 template <typename alternative_t>
143 constexpr decltype(auto) get_or(alternative_t && alternative) const && noexcept
144 {
145 return get_or_impl(std::move(*this), alternative, std::forward<alternative_t>(alternative));
146 }
147
149 template <typename query_t>
150 static constexpr bool exists() noexcept
151 {
152 return pack_traits::contains<query_t, configs_t...>;
153 }
155 template <template <typename ...> typename query_t>
156 static constexpr bool exists() noexcept
157 {
158 return (pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...> > -1);
159 }
161
181 template <typename other_configuration_t>
183 requires (is_config_element_combineable_v<configs_t, std::remove_cvref_t<other_configuration_t>> && ...)
185 constexpr auto append(other_configuration_t && other_config) const
186 {
187 if constexpr (detail::config_element<std::remove_cvref_t<other_configuration_t>>)
188 {
190 {
191 std::tuple_cat(static_cast<base_type>(*this),
192 std::tuple{std::forward<other_configuration_t>(other_config)})
193 };
194 }
195 else
196 {
197 // The following type aliases are needed to extract the correct reference and const qualifiers for the
198 // given `other_configuration_t` type (input parameter).
199 // Note the alternative would be to repeat multiple interfaces with `other_config_t &`,
200 // `other_config_t const &`, `other_config_t &&` and `other_config_t const &&`.
201
202 // Get the actual base tuple type from the other configuration.
203 using other_base_t = typename std::remove_cvref_t<other_configuration_t>::base_type;
204
205 // The other base tuple type matching the reference type and the const qualifier of the input parameter.
206 using other_base_same_modifier_t = detail::transfer_type_modifier_onto_t<other_configuration_t,
207 other_base_t>;
208
209 // Form a new seqan3::configuration type with the concatenated configuration element types of this and the
210 // other configuration.
211 using other_configs_list_t = detail::transfer_template_args_onto_t<other_base_t, type_list>;
212 using appended_configuration_t =
213 detail::transfer_template_args_onto_t<list_traits::concat<type_list<configs_t...>,
214 other_configs_list_t>,
216
217 // Concatenate the two configurations using their base tuple types.
218 return appended_configuration_t{std::tuple_cat(static_cast<base_type>(*this),
219 std::forward<other_base_same_modifier_t>(other_config))};
220 }
221 }
222
227 template <typename query_t>
228 [[nodiscard]] constexpr auto remove() const
230 requires (exists<query_t>())
232 {
233 constexpr int index = pack_traits::find<query_t, configs_t...>;
234 return remove_at<index>();
235 }
236
238 template <template <typename ...> typename query_t>
239 [[nodiscard]] constexpr auto remove() const
241 requires (exists<query_t>())
243 {
244 constexpr int index = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke,
245 configs_t...>;
246 return remove_at<index>();
247 }
249
250private:
251
256 template <typename ..._configs_t>
257 explicit constexpr configuration(std::tuple<_configs_t...> const & cfg) : base_type{cfg}
258 {}
259
261 template <typename ..._configs_t>
262 explicit constexpr configuration(std::tuple<_configs_t...> && cfg) : base_type{std::move(cfg)}
263 {}
265
275 template <int index>
276 [[nodiscard]] constexpr auto remove_at() const
277 {
278 static_assert((index >= 0) && (index < sizeof...(configs_t)), "Index to remove from config is out of bounds.");
279
280 auto [head, middle] = tuple_split<index>(static_cast<base_type>(*this));
281 auto tail = tuple_pop_front(middle);
282
283 using head_list_t = detail::transfer_template_args_onto_t<decltype(head), type_list>;
284 using tail_list_t = detail::transfer_template_args_onto_t<decltype(tail), type_list>;
285 using concat_list_t = list_traits::concat<head_list_t, tail_list_t>;
286 using new_configuration_t = detail::transfer_template_args_onto_t<concat_list_t, configuration>;
287
288 return new_configuration_t{std::tuple_cat(std::move(head), std::move(tail))};
289 }
291
309 template <typename this_t, typename query_t, typename alternative_t>
310 static constexpr decltype(auto) get_or_impl(this_t && me,
311 query_t const & SEQAN3_DOXYGEN_ONLY(query),
312 alternative_t && alternative) noexcept
313 {
314 if constexpr (exists<query_t>())
315 {
316 return get<query_t>(std::forward<this_t>(me));
317 }
318 else
319 {
320 using ret_type = remove_rvalue_reference_t<decltype(alternative)>;
321 return static_cast<ret_type>(alternative);
322 }
323 }
324
326 template <typename this_t,
327 template <typename ...> typename query_template_t, typename ...parameters_t,
328 typename alternative_t>
329 static constexpr decltype(auto) get_or_impl(this_t && me,
330 query_template_t<parameters_t...> const &,
331 alternative_t && alternative) noexcept
332 {
333 if constexpr (exists<query_template_t>())
334 {
335 return get<query_template_t>(std::forward<this_t>(me));
336 }
337 else
338 {
339 using ret_type = remove_rvalue_reference_t<decltype(alternative)>;
340 return static_cast<ret_type>(alternative);
341 }
342 }
343};
344
352template <detail::config_element config_t>
355
375template <typename lhs_config_t, typename rhs_config_t>
377 requires (is_config_element_combineable_v<std::remove_cvref_t<lhs_config_t>, std::remove_cvref_t<rhs_config_t>>)
379constexpr auto operator|(lhs_config_t && lhs, rhs_config_t && rhs)
380{
381 if constexpr (detail::config_element<std::remove_cvref_t<lhs_config_t>>)
382 return configuration{std::forward<lhs_config_t>(lhs)}.append(std::forward<rhs_config_t>(rhs));
383 else
384 return std::forward<lhs_config_t>(lhs).append(std::forward<rhs_config_t>(rhs));
385}
386
418template <template <typename ...> class query_t, typename ...configs_t>
419constexpr auto & get(configuration<configs_t...> & config) noexcept
420{
421 constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
422 static_assert(pos > -1, "Access error: The requested type is not contained.");
423
424 return get<pos>(config);
425}
426
428template <template <typename ...> class query_t, typename ...configs_t>
429constexpr auto const & get(configuration<configs_t...> const & config) noexcept
430{
431 constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
432 static_assert(pos > -1, "Access error: The requested type is not contained.");
433
434 return get<pos>(config);
435}
436
438template <template <typename ...> class query_t, typename ...configs_t>
439constexpr auto && get(configuration<configs_t...> && config) noexcept
440{
441 constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
442 static_assert(pos > -1, "Access error: The requested type is not contained.");
443
444 return get<pos>(std::move(config));
445}
446
448template <template <typename ...> class query_t, typename ...configs_t>
449constexpr auto const && get(configuration<configs_t...> const && config) noexcept
450{
451 constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
452 static_assert(pos > -1, "Access error: The requested type is not contained.");
453
454 // TODO: change after GCC-7 bug with const && version of get in std::tuple is fixed.
455 // return get<pos>(std::move(config));
456 return std::move(get<pos>(config));
457}
459
460} // namespace seqan3::detail
461
462namespace std
463{
465
471template <seqan3::detail::config_element ... configs_t>
472struct tuple_size<seqan3::configuration<configs_t...>>
473{
475 static constexpr size_t value = std::tuple_size_v<typename seqan3::configuration<configs_t...>::base_type>;
476};
477
483template <size_t pos, seqan3::detail::config_element ... configs_t>
484struct tuple_element<pos, seqan3::configuration<configs_t...>>
485{
487 using type = std::tuple_element_t<pos, typename seqan3::configuration<configs_t...>::base_type>;
488};
490} //namespace std
Collection of elements to configure an algorithm.
Definition: configuration.hpp:45
constexpr decltype(auto) get_or(alternative_t &&alternative) const &&noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:143
constexpr auto append(other_configuration_t &&other_config) const
Returns a new configuration by appending the given configuration to the current one.
Definition: configuration.hpp:185
constexpr size_t size() const noexcept
Returns the number of contained config elements.
Definition: configuration.hpp:86
constexpr auto remove() const
Remove a config element from the configuration.
Definition: configuration.hpp:228
configuration(config_t) -> configuration< config_t >
Deduces the correct configuration element type from the passed seqan3::pipeable_config_element.
constexpr decltype(auto) get_or(alternative_t &&alternative) &&noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:136
constexpr configuration(configuration &&)=default
Defaulted.
constexpr decltype(auto) get_or(alternative_t &&alternative) &noexcept
Returns the stored configuration element if present otherwise the given alternative.
Definition: configuration.hpp:122
constexpr configuration & operator=(configuration const &)=default
Defaulted.
constexpr configuration & operator=(configuration &&)=default
Defaulted.
~configuration()=default
Defaulted.
constexpr configuration(config_element_t &&config_element)
Constructs a configuration from a single configuration element.
Definition: configuration.hpp:76
constexpr decltype(auto) get_or(alternative_t &&alternative) const &noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:129
constexpr configuration(configuration const &)=default
Defaulted.
constexpr configuration()=default
Defaulted.
static constexpr bool exists() noexcept
Checks if the given type exists in the tuple.
Definition: configuration.hpp:150
friend class configuration
Friend declaration for other instances of the configuration.
Definition: configuration.hpp:48
The <concepts> header from C++20's standard library.
Provides various auxiliary functions with which parts of the configurations can be checked.
Provides concepts for the configuration classes.
constexpr auto & get(configuration< configs_t... > &config) noexcept
Returns the stored element.
Definition: configuration.hpp:419
constexpr auto tuple_pop_front(tuple_t &&t)
Removes the first element of a tuple.
Definition: pop_front.hpp:42
decltype(detail::concat(lists_t{}...)) concat
Join two seqan3::type_list s into one.
Definition: traits.hpp:329
constexpr ptrdiff_t find
Get the index of the first occurrence of a type in a pack.
Definition: traits.hpp:187
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition: traits.hpp:210
constexpr bool contains
Whether a type occurs in a pack or not.
Definition: traits.hpp:228
The main SeqAn3 namespace.
Definition: cigar_operation_table.hpp:2
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:429
SeqAn specific customisations in the standard namespace.
Provides seqan3::tuple_pop_front.
Type that contains multiple types.
Definition: type_list.hpp:29
Provides type traits for working with templates.
Provides type traits seqan3::detail::transfer_type_modifier_onto.
T tuple_cat(T... args)
T tuple_size_v
Provides seqan3::type_list.