En fait, l'utilisation des paramètres de modèle de modèle est plutôt évidente. Une fois que vous apprenez que stdlib C ++ a un trou béant de ne pas définir d'opérateurs de sortie de flux pour les types de conteneurs standard, vous devez écrire quelque chose comme:
template<typename T>
static inline std::ostream& operator<<(std::ostream& out, std::list<T> const& v)
{
out << '[';
if (!v.empty()) {
for (typename std::list<T>::const_iterator i = v.begin(); ;) {
out << *i;
if (++i == v.end())
break;
out << ", ";
}
}
out << ']';
return out;
}
Ensuite, vous comprendrez que le code pour le vecteur est exactement le même, car forward_list est le même, en fait, même pour une multitude de types de cartes, c'est toujours le même. Ces classes de modèles n'ont rien en commun, à l'exception de la méta-interface / du protocole, et l'utilisation du paramètre de modèle de modèle permet de capturer la similitude dans chacun d'eux. Avant de procéder à l'écriture d'un modèle, il convient de vérifier une référence pour rappeler que les conteneurs de séquence acceptent 2 arguments de modèle - pour le type de valeur et l'allocateur. Bien que l'allocateur soit par défaut, nous devons toujours tenir compte de son existence dans notre opérateur de modèle <<:
template<template <typename, typename> class Container, class V, class A>
std::ostream& operator<<(std::ostream& out, Container<V, A> const& v)
...
Voila, cela fonctionnera automatiquement pour tous les conteneurs de séquence actuels et futurs adhérant au protocole standard. Pour ajouter des cartes au mélange, il faudrait jeter un œil à la référence pour noter qu'elles acceptent 4 paramètres de modèle, nous aurions donc besoin d'une autre version de l'opérateur << ci-dessus avec le paramètre de modèle de modèle à 4 arguments. Nous verrions également que std: pair essaie d'être rendu avec l'opérateur 2-arg << pour les types de séquence que nous avons définis précédemment, donc nous fournirions une spécialisation juste pour std :: pair.
De plus, avec C + 11 qui autorise les modèles variadiques (et devrait donc autoriser les arguments de modèle de modèle variadique), il serait possible d'avoir un seul opérateur << pour les gouverner tous. Par exemple:
#include <iostream>
#include <vector>
#include <deque>
#include <list>
template<typename T, template<class,class...> class C, class... Args>
std::ostream& operator <<(std::ostream& os, const C<T,Args...>& objs)
{
os << __PRETTY_FUNCTION__ << '\n';
for (auto const& obj : objs)
os << obj << ' ';
return os;
}
int main()
{
std::vector<float> vf { 1.1, 2.2, 3.3, 4.4 };
std::cout << vf << '\n';
std::list<char> lc { 'a', 'b', 'c', 'd' };
std::cout << lc << '\n';
std::deque<int> di { 1, 2, 3, 4 };
std::cout << di << '\n';
return 0;
}
Production
std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = float, C = vector, Args = <std::__1::allocator<float>>]
1.1 2.2 3.3 4.4
std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = char, C = list, Args = <std::__1::allocator<char>>]
a b c d
std::ostream &operator<<(std::ostream &, const C<T, Args...> &) [T = int, C = deque, Args = <std::__1::allocator<int>>]
1 2 3 4