Loading...
Searching...
No Matches
adaptor_base.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 <ranges>
#include <tuple>
#include <seqan3/core/platform.hpp>
namespace seqan3::detail
{
// ============================================================================
// forwards
// ============================================================================
template <typename left_adaptor_t, typename right_adaptor_t>
class combined_adaptor;
// ============================================================================
// adaptor_base
// ============================================================================
template <typename derived_type, typename... stored_args_ts>
class adaptor_base
{
private:
std::tuple<stored_args_ts...> arguments;
template <typename urng_t, size_t... Is>
constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) const &
{
// std::get returns lvalue-reference to value, but we need to copy the values
// so that the view does not depend on the functor
return static_cast<derived_type const &>(*this).impl(
std::forward<urng_t>(urange),
std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(arguments))...);
}
template <typename urng_t, size_t... Is>
constexpr auto pass_args_to_impl(urng_t && urange, std::index_sequence<Is...> const &) &&
{
// move out values, because we don't need them anymore (*this is temporary)
return static_cast<derived_type &&>(*this).impl(
std::forward<urng_t>(urange),
std::tuple_element_t<Is, std::tuple<stored_args_ts...>>(std::get<Is>(std::move(arguments)))...);
}
friend derived_type;
public:
// a default constructor is not provided, however the constructor below might be one.
constexpr adaptor_base(adaptor_base const &) noexcept = default;
constexpr adaptor_base(adaptor_base &&) noexcept = default;
constexpr adaptor_base & operator=(adaptor_base const &) noexcept = default;
constexpr adaptor_base & operator=(adaptor_base &&) noexcept = default;
~adaptor_base() noexcept = default;
constexpr adaptor_base(stored_args_ts... args)
noexcept(noexcept(std::tuple<stored_args_ts...>{std::forward<stored_args_ts>(args)...})) :
arguments{std::forward<stored_args_ts>(args)...}
{}
template <std::ranges::input_range urng_t>
constexpr auto operator()(urng_t && urange) const &
{
return pass_args_to_impl(std::forward<urng_t>(urange), std::make_index_sequence<sizeof...(stored_args_ts)>{});
}
template <std::ranges::input_range urng_t>
constexpr auto operator()(urng_t && urange) &&
{
return std::move(*this).pass_args_to_impl(std::forward<urng_t>(urange),
std::make_index_sequence<sizeof...(stored_args_ts)>{});
}
template <typename arg_t>
constexpr friend auto operator|(arg_t && arg, derived_type const & me)
{
if constexpr (std::ranges::input_range<arg_t>)
return me(std::forward<arg_t>(arg));
else
return combined_adaptor{std::forward<arg_t>(arg), me};
}
template <typename arg_t>
constexpr friend auto operator|(arg_t && arg, derived_type && me)
{
if constexpr (std::ranges::input_range<arg_t>)
return std::move(me)(std::forward<arg_t>(arg));
else
return combined_adaptor{std::forward<arg_t>(arg), std::move(me)};
}
template <typename arg_t>
constexpr friend auto operator|(adaptor_base const & me, arg_t && arg)
{
return combined_adaptor{static_cast<derived_type const &>(me), std::forward<arg_t>(arg)};
}
template <typename arg_t>
constexpr friend auto operator|(adaptor_base && me, arg_t && arg)
{
return combined_adaptor{static_cast<derived_type &&>(me), std::forward<arg_t>(arg)};
}
};
// ============================================================================
// combined_adaptor
// ============================================================================
template <typename left_adaptor_t, typename right_adaptor_t>
class combined_adaptor :
public adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>
{
private:
using base_type = adaptor_base<combined_adaptor<left_adaptor_t, right_adaptor_t>, left_adaptor_t, right_adaptor_t>;
friend base_type;
template <std::ranges::input_range urng_t, typename left_adaptor_t_, typename right_adaptor_t_>
static auto impl(urng_t && urange, left_adaptor_t_ && left_adaptor, right_adaptor_t_ && right_adaptor)
{
return std::forward<urng_t>(urange) | std::forward<left_adaptor_t_>(left_adaptor)
| std::forward<right_adaptor_t_>(right_adaptor);
}
public:
constexpr combined_adaptor() = default;
constexpr combined_adaptor(combined_adaptor const &) noexcept = default;
constexpr combined_adaptor(combined_adaptor &&) noexcept = default;
constexpr combined_adaptor & operator=(combined_adaptor const &) noexcept = default;
constexpr combined_adaptor & operator=(combined_adaptor &&) noexcept = default;
~combined_adaptor() noexcept = default;
using base_type::base_type;
constexpr combined_adaptor(left_adaptor_t l, right_adaptor_t r) :
base_type{std::forward<left_adaptor_t>(l), std::forward<right_adaptor_t>(r)}
{}
};
} // namespace seqan3::detail
std::forward
T forward(T... args)
platform.hpp
Provides platform and dependency checks.
tuple
Hide me