Pretty-print std::tuple
C'est une suite à ma question précédente sur impression des conteneurs STL, pour lequel nous avons réussi à développer un très élégant et entièrement de solution générale.
Dans cette prochaine étape, je voudrais inclure d'impression pour std::tuple<Args...>
, à l'aide de variadic templates (si ce n'est strictement C++11). Pour std::pair<S,T>
, je dis simplement
std::ostream & operator<<(std::ostream & o, const std::pair<S,T> & p)
{
return o << "(" << p.first << ", " << p.second << ")";
}
Ce qui est l'analogue de la construction pour l'impression d'un tuple?
J'ai essayé différents bits de l'argument de modèle de pile déballage, en passant indices autour et à l'aide de SFINAE à découvrir quand je suis au dernier élément, mais sans succès. Je ne devrais pas vous importuner avec mon code cassé; la description du problème, je l'espère, straight-forward assez. Essentiellement, je tiens a le comportement suivant:
auto a = std::make_tuple(5, "Hello", -0.1);
std::cout << a << std::endl; //prints: (5, "Hello", -0.1)
Points de Bonus pour le même niveau de généralité (char/wchar_t, paire de délimiteurs) comme la question précédente!
- Quelqu'un a mis tout le code ici dans une bibliothèque? Ou même une .php-avec-tout-dans lequel on peut saisir et utiliser?
- Peut-être que cxx-prettyprint? C'est ce que j'avais besoin de ce code pour.
Vous devez vous connecter pour publier un commentaire.
Yay, les indices~
Live exemple sur Ideone.
Pour le délimiteur de trucs, il suffit d'ajouter ces partielle spécialisations:
et modifier le
operator<<
etprint_tuple
en conséquence:Et
TuplePrinter
n'a pas deoperator<<
.basic_ostream
etc) devrait être facile à partir d'ici.struct TuplePrinter
avec seulement basées sur des modèles de fonctions lors de l'utilisation de C++0x/C++11?class Tuple
pour laoperator<<
surcharge serait - il aller chercher de tout et de toutes les choses. Il aurait besoin d'être une contrainte, ce qui implique un peu de la nécessité pour une sorte de variadic arguments.operator<<
doit retournerstd::basic_ostream<Ch,Traits>&
au lieu destd::ostream&
et b) il ne fonctionne pas avec les tuples vides, c'est à dire,std::tuple<>
.swallow{(os << get<Is>(t))...};
.::std
). Il serait mieux comme une fonction qui est appelée (éventuellement qualifié) pour éviter de recherche de défaut afin de localiser l'exploitant.print_pretty
avec une expression de modèlepretty<T>
avec une surcharge<<
que de manière récursive poignées jolie impression iterables et de tuple-aime, pour retomber surostream << t
, puis un Koenigstd
activéostream << to_string(t)
, avec max la longueur de la ligne et l'indentation et la longue liste tableification, et la comme. Vous vous retrouvez avec une bibliothèque, pas une réponse.J'ai eu ce travail d'amende dans le C++11 (gcc 4.7). Il y a je suis sûr que certains pièges, je n'ai pas envisagé, mais je pense que le code est facile à lire et à et pas compliqué. La seule chose qui peut être étrange est la "garde" struct tuple_printer que de nous assurer de mettre fin lorsque le dernier élément est atteint. Autre chose étrange, peut-être sizeof...(Types) qui retourne le nombre de types de Types de type de pack. Il est utilisé pour déterminer l'indice du dernier élément (taille...(Types) - 1).
std::make_tuple()
. mais au moment de l'impression qu'il enmain()
, il jette à un groupe d'erreurs!, Des suggestions sur la façon plus simple d'imprimer les n-uplets?Je suis surpris de la mise en œuvre sur cppreference n'a pas déjà été posté ici, donc je vais le faire pour la postérité. Il est caché dans la doc pour
std::tuple_cat
de sorte qu'il n'est pas facile à trouver. Il utilise un garde struct comme certains des autres solutions ici, mais je pense que c'est finalement plus simple et plus facile à suivre.Et un test:
De sortie:
Démonstration En Direct
En C++17 nous pouvons accomplir cela avec un peu moins de code en profitant de Plier les expressions, en particulier unaire de gauche pli:
Démonstration En Direct sorties:
donné
Explication
Notre unaire de gauche pli est de la forme
où
op
dans notre scénario est l'opérateur virgule, etpack
est l'expression contenant notre tuple dans une non développés contexte comme:Donc, si j'ai un n-uplet de la sorte:
Et un
std::integer_sequence
dont les valeurs sont spécifiées par un non-type de modèle (voir code ci-dessus)Alors l'expression
Obtient élargi en
Qui permet d'imprimer
Qui est brut, nous avons donc besoin de faire un peu plus de la ruse pour ajouter une virgule de séparation à être imprimée pour la première fois, sauf si c'est le premier élément.
Pour accomplir cela, nous allons modifier l'
pack
partie de la fois l'expression d'imprimer" ,"
si l'indice actuelI
n'est pas le premier, d'où le(I == 0? "" : ", ")
partie*:Et maintenant nous allons obtenir
Qui ressemble plus belle (Note: je voulais le même résultat que cette réponse)
*Remarque: Vous pouvez procéder de la virgule de séparation dans une variété de façons de faire que ce que j'ai. J'ai d'abord ajouté des virgules conditionnellement après au lieu de avant par des tests contre les
std::tuple_size<TupType>::value - 1
, mais c'était trop long, donc j'ai testé au lieu contresizeof...(I) - 1
, mais à la fin j'ai copié Xeo et nous avons fini avec ce que j'ai.if constexpr
pour le cas de base.Basée sur exemple sur Le Langage de Programmation C++ Par Bjarne Stroustrup, page 817:
De sortie:
Basé sur AndyG code en C++17
avec sortie:
et voici une autre mise en œuvre:
https://github.com/galaxyeye/atlas/blob/master/atlas/io/tuple.h
avec le code de test :
https://github.com/galaxyeye/atlas/blob/master/libs/serialization/test/tuple.cpp
profiter 🙂
Un autre, similaire à @Tony Olsson, y compris une spécialisation pour le tuple vide, comme suggéré par @Kerrek SB.