Loading...
Searching...
No Matches
default_printer.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 <functional>
#include <iosfwd>
#include <tuple>
#include <utility>
#include <seqan3/core/platform.hpp>
namespace seqan3
{
// clang-format off
struct no_printer_found{};
template <typename> struct advanceable_alignment_coordinate_printer {};
template <typename> struct alignment_matrix_printer {};
template <typename> struct alignment_printer {};
template <typename> struct alignment_result_printer {};
template <typename> struct alphabet_printer {};
template <typename> struct cigar_printer {};
template <typename> struct debug_stream_printer {};
template <typename> struct dynamic_bitset_printer {};
template <typename> struct enumeration_printer {};
template <typename> struct input_range_printer {};
template <typename> struct integer_sequence_printer {};
template <typename> struct integral_printer {};
template <typename> struct mask_printer {};
template <typename> struct optional_printer {};
template <typename> struct sam_flag_printer {};
template <typename> struct sequence_printer {};
template <typename> struct search_result_printer {};
template <typename> struct simd_printer {};
template <typename> struct std_byte_printer {};
template <typename> struct std_variant_printer {};
template <typename> struct std_printer {};
template <typename> struct strong_type_printer {};
template <typename> struct char_sequence_printer {};
template <typename> struct trace_directions_printer {};
template <typename> struct tuple_printer {};
// clang-format on
template <typename printer_t, typename stream_t, typename arg_t>
concept printable_with = std::invocable<printer_t, stream_t, arg_t>;
template <typename type_t>
requires requires (std::ostream & cout, type_t const & value) {
{ cout << value };
}
struct std_printer<type_t>
{
template <typename stream_t, typename arg_t>
requires requires (stream_t & stream) { stream.stream; }
constexpr void operator()(stream_t & stream, arg_t && arg) const
{
*stream.stream << arg;
}
};
template <std::integral integral_t>
struct integral_printer<integral_t>
{
template <typename stream_t>
constexpr void operator()(stream_t & stream, integral_t const arg) const
{
// note that we assume here that we always can print all std::integral's,
// but this is not correct since std::cout << char32_t{5}; is not possible.
// since char32_t is also an alphabet, we avoid infinite recursion here.
if constexpr (printable_with<std_printer<integral_t>, stream_t &, integral_t>)
std::invoke(std_printer<integral_t>{}, stream, arg);
else
static_assert(std::same_as<integral_t *, void>, "This type is not printable.");
// We actually want `static_assert(false, "This type is not printable.");`.
// But this only works starting with GCC13. Before that, also the `if constexpr` branches that are not taken
// are evaluated and `static_assert(false)` will always result in an error. As a pre-GCC13 workaround,
// we can make the `false` dependent on some template type, which then will only be evaluated if the branch is
// taken.
}
};
template <template <typename> typename... printer_templates_t>
struct printer_order
{
protected:
template <typename stream_t, typename arg_t, typename... printers_t>
static constexpr size_t find_index()
{
size_t i = 0;
return ((printable_with<printers_t, stream_t, arg_t> ? false : ++i) && ...) ? sizeof...(printer_templates_t)
: i;
}
template <typename stream_t,
typename arg_t,
size_t i = find_index<stream_t, arg_t, printer_templates_t<arg_t>...>()>
using printer_for_t =
// first: the index of the printer that can print the arguments or sizeof...(printers_t) if no printer was found
// second: the tuple of instantiated printers extended with no_printer_found
std::tuple_element_t<i, std::tuple<printer_templates_t<arg_t>..., no_printer_found>>;
};
struct default_printer :
public printer_order<
debug_stream_printer,
alignment_result_printer, // type seqan3::alignment_result<>
search_result_printer, // type seqan3::search_result<>
alignment_printer, // concept seqan3::tuple_like<>
advanceable_alignment_coordinate_printer, // type seqan3::detail::advanceable_alignment_coordinate<>
alignment_matrix_printer, // concept seqan3::detail::matrix<>
trace_directions_printer, // type seqan3::detail::trace_directions
mask_printer, // type seqan3::mask
integral_printer, // concept std::integral
cigar_printer, // type seqan3::cigar
// NOTE: alphabet_printer needs the integral_printer overload, otherwise it might have infinite recursion due to
// char and uint being an alphabet
alphabet_printer, // concept seqan3::alphabet
sam_flag_printer, // type seqan3::sam_flag
simd_printer, // concept simd::simd_concept<>
dynamic_bitset_printer, // type seqan3::dynamic_bitset<>
// NOTE: In C++26, std::optional<T> is a view (and hence models std::ranges::input_range<>).
// So it needs to have priority over char_sequence_printer, integer_sequence_printer, and input_range_printer.
optional_printer, // type std::optional<> or std::nullopt_t
char_sequence_printer, // concept std::range::input_range<> with char value_type
integer_sequence_printer, // concept std::range::input_range<> with std::integral value_type
sequence_printer, // concept seqan3::sequence<>, i.e. std::range::input_range<> with seqan3::alphabet value_type
input_range_printer, // concept std::range::input_range<>
strong_type_printer, // concept seqan3::detail::derived_from_strong_type<>
enumeration_printer, // types for which seqan3::enumeration_names is overloaded
tuple_printer, // concept seqan3::tuple_like<>
std_byte_printer, // type std::byte
std_variant_printer, // type std::variant<>
std_printer // anything that can be printed by std::ostream
>
{
public:
template <typename stream_t, typename arg_t>
requires printable_with<printer_for_t<stream_t &, std::remove_cvref_t<arg_t>>, stream_t &, arg_t>
constexpr void operator()(stream_t & stream, arg_t && arg) const
{
using printer_t = printer_for_t<stream_t &, std::remove_cvref_t<arg_t>>;
std::invoke(printer_t{}, stream, std::forward<arg_t>(arg));
}
};
} // namespace seqan3
std::ostream
seqan3::printable_with
Definition default_printer.hpp:67
std::forward
T forward(T... args)
functional
std::invoke
T invoke(T... args)
iosfwd
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
platform.hpp
Provides platform and dependency checks.
seqan3::advanceable_alignment_coordinate_printer
Definition default_printer.hpp:27
seqan3::alignment_matrix_printer
Definition default_printer.hpp:28
seqan3::alignment_printer
Definition default_printer.hpp:29
seqan3::alignment_result_printer
Definition default_printer.hpp:30
seqan3::alphabet_printer
Definition default_printer.hpp:31
seqan3::char_sequence_printer
Definition default_printer.hpp:49
seqan3::cigar_printer
Definition default_printer.hpp:32
seqan3::debug_stream_printer
Definition default_printer.hpp:33
seqan3::default_printer
The default printer that is used by seqan3::debug_stream.
Definition default_printer.hpp:221
seqan3::default_printer::operator()
constexpr void operator()(stream_t &stream, arg_t &&arg) const
The function call operator that is only defined if the type is printable.
Definition default_printer.hpp:231
seqan3::dynamic_bitset_printer
Definition default_printer.hpp:34
seqan3::enumeration_printer
Definition default_printer.hpp:35
seqan3::input_range_printer
Definition default_printer.hpp:36
seqan3::integer_sequence_printer
Definition default_printer.hpp:37
seqan3::integral_printer< integral_t >::operator()
constexpr void operator()(stream_t &stream, integral_t const arg) const
The function call operator that prints the integral to the stream.
Definition default_printer.hpp:118
seqan3::integral_printer
Definition default_printer.hpp:38
seqan3::mask_printer
Definition default_printer.hpp:39
seqan3::no_printer_found
A tag that indicates that no printer was found for the given type.
Definition default_printer.hpp:26
seqan3::optional_printer
Definition default_printer.hpp:40
seqan3::printer_order
The printer_order is a variadic template that defines the order of the printers.
Definition default_printer.hpp:146
seqan3::printer_order::find_index
static constexpr size_t find_index()
Find the index of the first printer that can print the argument.
Definition default_printer.hpp:156
seqan3::printer_order::printer_for_t
std::tuple_element_t< i, std::tuple< printer_templates_t< arg_t >..., no_printer_found > > printer_for_t
The type of the printer that can print the argument to the stream.
Definition default_printer.hpp:175
seqan3::sam_flag_printer
Definition default_printer.hpp:41
seqan3::search_result_printer
Definition default_printer.hpp:43
seqan3::sequence_printer
Definition default_printer.hpp:42
seqan3::simd_printer
Definition default_printer.hpp:44
seqan3::std_byte_printer
Definition default_printer.hpp:45
seqan3::std_printer< type_t >::operator()
constexpr void operator()(stream_t &stream, arg_t &&arg) const
The function call operator that prints the value to the stream.
Definition default_printer.hpp:95
seqan3::std_printer
Definition default_printer.hpp:47
seqan3::std_variant_printer
Definition default_printer.hpp:46
seqan3::strong_type_printer
Definition default_printer.hpp:48
seqan3::trace_directions_printer
Definition default_printer.hpp:50
seqan3::tuple_printer
Definition default_printer.hpp:51
tuple
utility
Hide me