2009-06-11 8 views
2

Ok, j'ai donc écrit un algorithme de type stl appelé cartesian_product. Pour ceux qui ne le savent pas, le produit cartésien est constitué de toutes les paires d'éléments possibles à partir de deux ensembles. Ainsi, le produit cartésien de {1, 2, 3} et {10, 20, 30} estAide sur les modèles de modèles C++

{(1,10), (1,20), (1,30), (2,10), (2,20), (2,30), (3,10), (3,20), (3,30)}

Ainsi la fonction ressemble

template <typename InIt1, typename InIt2, typename OutIt> 
void 
cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out) 
{ 
    for (; first1 != last1; ++first1) 
     for (InIt2 it = first2; it != last2; ++it) 
      *out++ = std::make_pair(*first1, *it); 
} 

Il n'y a pas typedefs modèle, donc je fait une classe de traits pour maintenir le type qui la iterator de sortie est de:

template <typename ObjA, typename ObjB, template <typename> class Container> 
struct cartesian_product_traits 
{ 
    typedef Container<std::pair<ObjA, ObjB> > type; 
}; 

alors je peux dire:

typedef cartesian_product_traits<int, int, std::vector>::type IntPairList; 
IntPairList my_list; 
cartesian_product(v1.begin(), v1.end(), 
        v2.begin(), v2.end(), 
        std::back_inserter(my_list); 

mais cela ne semble pas compiler. Je reçois une belle erreur:

error C3201: the template parameter list for class template 'std::vector' does not match the template parameter list for template parameter 'Container' 

Donc je suis perplexe. Comment puis-je faire fonctionner ça?

Répondre

8

La liste des paramètres du modèle pour le vecteur est non seulement un élément, il faut être deux:

template < class T, class Allocator = allocator<T> > class vector 

donc pour accepter vecteur, vous devez avoir un paramètre de modèle de modèle avec deux blancs:

template <typename ObjA, typename ObjB, template <typename, typename> class Container> 
struct cartesian_product_traits 

Édité: couper quelques conseils, mal interprété votre code.

La façon de le faire correctement serait d'utiliser une macro variadique sur le paramètre de modèle de modèle:

template <typename ObjA, typename ObjB, template <typename ...> class Container> 
struct cartesian_product_traits 

Mais c'est loin d'être une norme. Si elle était mon code, je serais probablement juste avoir les consommateurs martèlent à le gabarit:

std::vector< std::pair<int, int> > 

est plus courte que

cartesian_product_traits<int, int, vector> 

et celui-ci ne serait utile que la définition d'un produit cartésien modifié.

2

std::vector Le modèle de 's est en fait assez complexe (avec des paramètres de modèle optionnels pour les allocateurs & c) - et d'autres conteneurs dans le stdlib ne sont pas plus simples non plus. Dans vos chaussures, je ferais le troisième paramètre de cartesian_product_traits dans une plaine typename PairsContainer et dépend de l'appelant pour aller au petit problème de le passer comme un conteneur approprié de paires.

+0

+1 vote juste pour dire "& c" pour "etc." – rlbond

+2

-1 vote pour révoquer cet upvote de @rlbond –