Maison  >  Article  >  développement back-end  >  Comment joliment imprimer `std::tuple` en C 11 à l'aide de modèles variadiques ?

Comment joliment imprimer `std::tuple` en C 11 à l'aide de modèles variadiques ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-07 17:44:03765parcourir

How to Pretty-Print `std::tuple` in C  11 Using Variadic Templates?

Std::tuple à jolie impression

Cet article est la suite d'une discussion précédente sur les conteneurs STL à jolie impression, où nous avons développé une solution élégante et générale pour cette tâche.

Énoncé du problème

Dans cette extension, nous visons à inclure une fonctionnalité d'impression jolie pour les objets std::tuple à l'aide de modèles variadiques, spécifiquement adaptés à C 11. . Inspirés de l'exemple précédent pour std::pair, nous recherchons une construction analogue pour les tuples. Le comportement souhaité est le suivant :

auto a = std::make_tuple(5, "Hello", -0.1);
std::cout << a << std::endl; // prints: (5, "Hello", -0.1)

De plus, nous visons à incorporer le même niveau de généralité que la question précédente, y compris la prise en charge de différents types de caractères et de délimiteurs de paires personnalisables.

Solution

En exploitant l'approche basée sur les indices, nous pouvons construire une solution en utilisant l'extrait de code suivant :

namespace aux{
template<std::size_t... Is> struct seq{};

template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};

template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch,Tr>& os, Tuple const& t, seq<Is...>)
{
  using swallow = int[];
  (void)swallow{0, (void(
    os << (Is == 0? "" : ", ") << std::get<Is>(t)
  ), 0)...};
}
}

template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t)
    -> std::basic_ostream<Ch, Tr>&
{
  os << "(";
  aux::print_tuple(os, t, aux::gen_seq<sizeof...(Args)>()
);
  return os << ")";
}

Pour la personnalisation des délimiteurs, nous pouvons ajouter ces partiels spécialisations :

// Delimiters for tuple
template<class... Args>
struct delimiters<std::tuple<Args...>, char> {
  static const delimiters_values<char> values;
};

template<class... Args>
const delimiters_values<char> delimiters<std::tuple<Args...>, char>::values =
    { "(", ", ", ")" };

template<class... Args>
struct delimiters<std::tuple<Args...>, wchar_t> {
  static const delimiters_values<wchar_t> values;
};

template<class... Args>
const delimiters_values<wchar_t> delimiters<
    std::tuple<Args...>, wchar_t
>::values = { L"(", L", ", L")" };

Avec ces modifications, l'opérateur<< et les fonctions print_tuple peuvent être mises à jour pour intégrer la personnalisation du délimiteur :

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch, Tr>& os, Tuple const& t, seq<Is...>)
{
  using swallow = int[];
  char const* delim = delimiters<Tuple, Ch>::values.delimiter;
  if(!delim) delim = "";
  (void)swallow{0, (void(
    os << (Is == 0? "" : delim) << std::get<Is>(t)
  ), 0)...};
}
template<class Ch, class Tr, class... Args>
auto operator<<(std::basic_ostream<Ch, Tr>& os, std::tuple<Args...> const& t)
    -> std::basic_ostream<Ch, Tr>&
{
  typedef std::tuple<Args...> tuple_t;
  if(delimiters<tuple_t, Ch>::values.prefix != 0)
    os << delimiters<tuple_t,char>::values.prefix;

  print_tuple(os, t, aux::gen_seq<sizeof...(Args)>()
);

  if(delimiters<tuple_t, Ch>::values.postfix != 0)
    os << delimiters<tuple_t,char>::values.postfix;

  return os;
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn