Maison >développement back-end >C++ >Comment joliment imprimer `std::tuple` en C 11 à l'aide de modèles variadiques ?
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!