text: // -----------------------------------------------------------------------------------------------------
  // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
  // Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
  // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
  // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
  // -----------------------------------------------------------------------------------------------------
  
  /*!\file
   * \author Hannes Hauswedell <hannes.hauswedell AT fu-berlin.de>
   * \brief Provides seqan3::debug_stream and related types.
   */
  
  #pragma once
  
  #include <seqan3/alphabet/concept.hpp>
  #include <seqan3/core/concept/tuple.hpp>
  #include <seqan3/core/detail/debug_stream_type.hpp>
  #include <seqan3/std/ranges>
  
  namespace seqan3
  {
  /*!\name Formatted output overloads
   * \{
   */
  } // namespace seqan3
  
  namespace seqan3::detail
  {
  
  //!\brief Helper function to print elements of a tuple separately.
  template <typename char_t, typename tuple_t, std::size_t ...I>
  void print_tuple(debug_stream_type<char_t> & s, tuple_t && t, std::index_sequence<I...> const &)
  {
      using std::get;
      s << '(';
      ((s << (I == 0 ? "" : ",") << get<I>(t)), ...);
      s << ')';
  }
  
  } // namespace seqan3::detail
  
  namespace seqan3
  {
  
  /*!\brief All tuples can be printed by printing their elements separately.
   * \tparam tuple_t Type of the tuple to be printed; must model seqan3::tuple_like.
   * \param s The seqan3::debug_stream.
   * \param t The tuple.
   * \relates seqan3::debug_stream_type
   */
  template <typename tuple_t, typename char_t>
  //!\cond
      requires !std::ranges::input_range<tuple_t> &&
               !alphabet<tuple_t> && // exclude alphabet_tuple_base
               tuple_like<remove_cvref_t<tuple_t>>
  //!\endcond
  inline debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & s, tuple_t && t)
  {
      detail::print_tuple(s, std::forward<tuple_t>(t),
                          std::make_index_sequence<std::tuple_size_v<remove_cvref_t<tuple_t>>>{});
      return s;
  }
  
  //!\}
  
  } // namespace seqan3
  