Loading...
Searching...
No Matches
configuration.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <concepts>
#include <seqan3/core/configuration/detail/concept.hpp>
#include <seqan3/core/configuration/detail/configuration_utility.hpp>
#include <seqan3/core/detail/template_inspection.hpp>
#include <seqan3/core/detail/transfer_type_modifier_onto.hpp>
#include <seqan3/utility/tuple/pop_front.hpp>
#include <seqan3/utility/type_list/type_list.hpp>
namespace seqan3
{
// ----------------------------------------------------------------------------
// configuration
// ----------------------------------------------------------------------------
template <detail::config_element... configs_t>
class configuration : public std::tuple<configs_t...>
{
template <detail::config_element... _configs_t>
friend class configuration;
public:
using base_type = std::tuple<configs_t...>;
constexpr configuration() = default;
constexpr configuration(configuration const &) = default;
constexpr configuration(configuration &&) = default;
constexpr configuration & operator=(configuration const &) = default;
constexpr configuration & operator=(configuration &&) = default;
~configuration() = default;
template <typename config_element_t>
requires (!std::same_as<std::remove_cvref_t<config_element_t>, configuration>)
&& detail::config_element<std::remove_cvref_t<config_element_t>>
constexpr configuration(config_element_t && config_element) :
base_type{std::forward<config_element_t>(config_element)}
{}
constexpr size_t size() const noexcept
{
return std::tuple_size_v<base_type>;
}
template <typename alternative_t>
constexpr decltype(auto) get_or(alternative_t && alternative) & noexcept
{
return get_or_impl(*this, alternative, std::forward<alternative_t>(alternative));
}
template <typename alternative_t>
constexpr decltype(auto) get_or(alternative_t && alternative) const & noexcept
{
return get_or_impl(*this, alternative, std::forward<alternative_t>(alternative));
}
template <typename alternative_t>
constexpr decltype(auto) get_or(alternative_t && alternative) && noexcept
{
return get_or_impl(std::move(*this), alternative, std::forward<alternative_t>(alternative));
}
template <typename alternative_t>
constexpr decltype(auto) get_or(alternative_t && alternative) const && noexcept
{
return get_or_impl(std::move(*this), alternative, std::forward<alternative_t>(alternative));
}
template <typename query_t>
static constexpr bool exists() noexcept
{
return pack_traits::contains<query_t, configs_t...>;
}
template <template <typename...> typename query_t>
static constexpr bool exists() noexcept
{
return (pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...> > -1);
}
template <typename other_configuration_t>
requires (is_config_element_combineable_v<configs_t, std::remove_cvref_t<other_configuration_t>> && ...)
constexpr auto append(other_configuration_t && other_config) const
{
if constexpr (detail::config_element<std::remove_cvref_t<other_configuration_t>>)
{
return configuration<configs_t..., std::remove_cvref_t<other_configuration_t>>{
std::tuple_cat(static_cast<base_type>(*this),
std::tuple{std::forward<other_configuration_t>(other_config)})};
}
else
{
// The following type aliases are needed to extract the correct reference and const qualifiers for the
// given `other_configuration_t` type (input parameter).
// Note the alternative would be to repeat multiple interfaces with `other_config_t &`,
// `other_config_t const &`, `other_config_t &&` and `other_config_t const &&`.
// Get the actual base tuple type from the other configuration.
using other_base_t = typename std::remove_cvref_t<other_configuration_t>::base_type;
// The other base tuple type matching the reference type and the const qualifier of the input parameter.
using other_base_same_modifier_t =
detail::transfer_type_modifier_onto_t<other_configuration_t, other_base_t>;
// Form a new seqan3::configuration type with the concatenated configuration element types of this and the
// other configuration.
using other_configs_list_t = detail::transfer_template_args_onto_t<other_base_t, type_list>;
using appended_configuration_t = detail::transfer_template_args_onto_t<
list_traits::concat<type_list<configs_t...>, other_configs_list_t>,
configuration>;
// Concatenate the two configurations using their base tuple types.
return appended_configuration_t{
std::tuple_cat(static_cast<base_type>(*this), std::forward<other_base_same_modifier_t>(other_config))};
}
}
template <typename query_t>
[[nodiscard]] constexpr auto remove() const
requires (exists<query_t>())
{
constexpr int index = pack_traits::find<query_t, configs_t...>;
return remove_at<index>();
}
template <template <typename...> typename query_t>
[[nodiscard]] constexpr auto remove() const
requires (exists<query_t>())
{
constexpr int index =
pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
return remove_at<index>();
}
private:
template <typename... _configs_t>
explicit constexpr configuration(std::tuple<_configs_t...> const & cfg) : base_type{cfg}
{}
template <typename... _configs_t>
explicit constexpr configuration(std::tuple<_configs_t...> && cfg) : base_type{std::move(cfg)}
{}
template <int index>
[[nodiscard]] constexpr auto remove_at() const
{
static_assert((index >= 0) && (index < sizeof...(configs_t)), "Index to remove from config is out of bounds.");
auto [head, middle] = tuple_split<index>(static_cast<base_type>(*this));
auto tail = tuple_pop_front(middle);
using head_list_t = detail::transfer_template_args_onto_t<decltype(head), type_list>;
using tail_list_t = detail::transfer_template_args_onto_t<decltype(tail), type_list>;
using concat_list_t = list_traits::concat<head_list_t, tail_list_t>;
using new_configuration_t = detail::transfer_template_args_onto_t<concat_list_t, configuration>;
return new_configuration_t{std::tuple_cat(std::move(head), std::move(tail))};
}
template <typename this_t, typename query_t, typename alternative_t>
static constexpr decltype(auto)
get_or_impl(this_t && me, query_t const & SEQAN3_DOXYGEN_ONLY(query), alternative_t && alternative) noexcept
{
if constexpr (exists<query_t>())
{
return get<query_t>(std::forward<this_t>(me));
}
else
{
using ret_type = remove_rvalue_reference_t<decltype(alternative)>;
return static_cast<ret_type>(alternative);
}
}
template <typename this_t,
template <typename...>
typename query_template_t,
typename... parameters_t,
typename alternative_t>
static constexpr decltype(auto)
get_or_impl(this_t && me, query_template_t<parameters_t...> const &, alternative_t && alternative) noexcept
{
if constexpr (exists<query_template_t>())
{
return get<query_template_t>(std::forward<this_t>(me));
}
else
{
using ret_type = remove_rvalue_reference_t<decltype(alternative)>;
return static_cast<ret_type>(alternative);
}
}
};
template <detail::config_element config_t>
configuration(config_t) -> configuration<config_t>;
template <typename lhs_config_t, typename rhs_config_t>
requires (is_config_element_combineable_v<std::remove_cvref_t<lhs_config_t>, std::remove_cvref_t<rhs_config_t>>)
constexpr auto operator|(lhs_config_t && lhs, rhs_config_t && rhs)
{
if constexpr (detail::config_element<std::remove_cvref_t<lhs_config_t>>)
return configuration{std::forward<lhs_config_t>(lhs)}.append(std::forward<rhs_config_t>(rhs));
else
return std::forward<lhs_config_t>(lhs).append(std::forward<rhs_config_t>(rhs));
}
template <template <typename...> class query_t, typename... configs_t>
constexpr auto & get(configuration<configs_t...> & config) noexcept
{
constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
static_assert(pos > -1, "Access error: The requested type is not contained.");
return get<pos>(config);
}
template <template <typename...> class query_t, typename... configs_t>
constexpr auto const & get(configuration<configs_t...> const & config) noexcept
{
constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
static_assert(pos > -1, "Access error: The requested type is not contained.");
return get<pos>(config);
}
template <template <typename...> class query_t, typename... configs_t>
constexpr auto && get(configuration<configs_t...> && config) noexcept
{
constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
static_assert(pos > -1, "Access error: The requested type is not contained.");
return get<pos>(std::move(config));
}
template <template <typename...> class query_t, typename... configs_t>
constexpr auto const && get(configuration<configs_t...> const && config) noexcept
{
constexpr auto pos = pack_traits::find_if<detail::is_same_configuration_f<query_t>::template invoke, configs_t...>;
static_assert(pos > -1, "Access error: The requested type is not contained.");
return get<pos>(std::move(config));
}
} // namespace seqan3
namespace std
{
template <seqan3::detail::config_element... configs_t>
struct tuple_size<seqan3::configuration<configs_t...>>
{
static constexpr size_t value = std::tuple_size_v<typename seqan3::configuration<configs_t...>::base_type>;
};
template <size_t pos, seqan3::detail::config_element... configs_t>
struct tuple_element<pos, seqan3::configuration<configs_t...>>
{
using type = std::tuple_element_t<pos, typename seqan3::configuration<configs_t...>::base_type>;
};
} //namespace std
seqan3::configuration
Collection of elements to configure an algorithm.
Definition configuration.hpp:42
seqan3::configuration::get_or
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:138
seqan3::configuration::size
constexpr size_t size() const noexcept
Returns the number of contained config elements.
Definition configuration.hpp:81
seqan3::configuration::configuration
configuration(config_t) -> configuration< config_t >
Deduces the correct configuration element type from the passed seqan3::pipeable_config_element.
seqan3::configuration::configuration
constexpr configuration(config_element_t &&config_element)
Constructs a configuration from a single configuration element.
Definition configuration.hpp:71
seqan3::configuration::get_or
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:131
seqan3::configuration::configuration
constexpr configuration(configuration &&)=default
Defaulted.
seqan3::configuration::remove
constexpr auto remove() const
Remove a config element from the configuration.
Definition configuration.hpp:218
seqan3::configuration::get_or
constexpr decltype(auto) get_or(alternative_t &&alternative) &noexcept
Returns the stored configuration element if present otherwise the given alternative.
Definition configuration.hpp:117
seqan3::configuration::operator=
constexpr configuration & operator=(configuration const &)=default
Defaulted.
seqan3::configuration::operator=
constexpr configuration & operator=(configuration &&)=default
Defaulted.
seqan3::configuration::~configuration
~configuration()=default
Defaulted.
seqan3::configuration::append
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:178
seqan3::configuration::get_or
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:124
seqan3::configuration::configuration
constexpr configuration(configuration const &)=default
Defaulted.
seqan3::configuration::configuration
constexpr configuration()=default
Defaulted.
seqan3::configuration::exists
static constexpr bool exists() noexcept
Checks if the given type exists in the tuple.
Definition configuration.hpp:145
seqan3::configuration::configuration
friend class configuration
Friend declaration for other instances of the configuration.
Definition configuration.hpp:45
configuration_utility.hpp
Provides various auxiliary functions with which parts of the configurations can be checked.
concept.hpp
Provides concepts for the configuration classes.
std::forward
T forward(T... args)
seqan3::is_config_element_combineable_v
constexpr bool is_config_element_combineable_v
Helper variable template to test if a configuration element is combineable with another configuration...
Definition core/configuration/detail/concept.hpp:127
seqan3::configuration::get
constexpr auto & get(configuration< configs_t... > &config) noexcept
Returns the stored element.
Definition configuration.hpp:402
seqan3::tuple_pop_front
constexpr auto tuple_pop_front(tuple_t &&t)
Removes the first element of a tuple.
Definition pop_front.hpp:39
seqan3::tuple_split
constexpr auto tuple_split(tuple_t< ts... > const &t)
Splits a tuple like data structure at the given position.
Definition split.hpp:87
seqan3::list_traits::concat
decltype(detail::concat(lists_t{}...)) concat
Join two seqan3::type_list s into one.
Definition type_list/traits.hpp:339
seqan3::pack_traits::find
constexpr ptrdiff_t find
Get the index of the first occurrence of a type in a pack.
Definition type_pack/traits.hpp:179
seqan3::pack_traits::find_if
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition type_pack/traits.hpp:202
seqan3::pack_traits::contains
constexpr bool contains
Whether a type occurs in a pack or not.
Definition type_pack/traits.hpp:220
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
seqan3::get
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:412
std
SeqAn specific customisations in the standard namespace.
pop_front.hpp
Provides seqan3::tuple_pop_front.
seqan3::type_list
Type that contains multiple types.
Definition type_list.hpp:26
template_inspection.hpp
Provides type traits for working with templates.
transfer_type_modifier_onto.hpp
Provides type traits seqan3::detail::transfer_type_modifier_onto.
std::tuple_cat
T tuple_cat(T... args)
std::tuple
std::tuple_size_v
T tuple_size_v
type_list.hpp
Provides seqan3::type_list.
Hide me