2013-08-12 4 views
3

J'ai besoin d'une variante du populaire indices trick, qui fait un produit cartésien de 2 séquences d'indices de longueurs éventuellement différentes. Pouvez-vous donner des conseils/exemples sur la façon dont cela pourrait être fait? Peut-être un lien vers une bibliothèque.générateur d'indices de produit cartésien

EDIT: je ne pouvais venir avec ceci:

template <typename ...T> struct list {}; 

template <typename T, typename U> 
struct pair 
{ 
    typedef T first; 
    typedef U second; 
}; 

template <std::size_t i> 
using index = std::integral_constant<std::size_t, i>; 

template <std::size_t ON, std::size_t M, std::size_t N, typename ...Ps> 
struct cartesian 
    : std::conditional<bool(N), 
     cartesian<ON, M, N - 1, pair<index<M>, index<N> >, Ps...>, 
     cartesian<ON, M - 1, ON, pair<index<M>, index<N> >, Ps...> 
    >::type 
{ 
}; 

template <std::size_t ON, typename ...Ps> 
struct cartesian<ON, 0, 0, Ps...> 
    : list<pair<index<0>, index<0> >, Ps...> 
{ 
}; 

template <std::size_t M, std::size_t N> 
struct make_cartesian : cartesian<N - 1, M - 1, N - 1> 
{ 
    static_assert(M > 0, "M has to be greater than 0"); 
    static_assert(N > 0, "N has to be greater than 0"); 
}; 
+0

Comment vous attendez-vous à ce que la séquence finale ressemble? Une liste de paires d'indices? Aussi, tout ce que vous avez déjà essayé? Vous devriez juste être capable de regarder comment un produit cartésien est fait pour les vecteurs/listes normaux et le transférer à TMP. – Xeo

+0

J'ai quitté la représentation des paires ouvertes, il pourrait être n'importe quoi, ils pourraient être «aplati» dans une seule séquence de taille égale. Je vais essayer plus tard dans la journée, ne devrait pas être trop dur, mais je pensais que quelqu'un pourrait simplement copier et coller du code écrit il ya longtemps :) – user1095108

Répondre

4

Voici une implémentation plutôt simple et ennuyeuse.

#include <cstdlib> 
#include <iostream> 

namespace ct { 

    template <typename, typename> 
    struct pair {}; 

    template <typename... a> 
    struct list {}; 

    template <typename a, typename... b> 
    struct cons_t; 

    template <typename a> 
    struct cons_t<a, list<>> 
    { 
    using type = list<a>; 
    }; 

    template <typename a, typename bh, typename... bt> 
    struct cons_t<a, list<bh, bt...>> 
    { 
    using type = list<a, bh, bt...>; 
    }; 

    template <typename a, typename... b> 
    struct concat_t; 

    template <typename b> 
    struct concat_t<list<>, b> 
    { 
    using type = b; 
    }; 

    template <typename b, typename ah, typename... at> 
    struct concat_t<list<ah, at...>, b> 
    { 
    using type = typename cons_t<ah, typename concat_t<list<at...>, b>::type>::type; 
    }; 

    template <typename a, typename b> 
    using cons = typename cons_t<a,b>::type; 
    template <typename a, typename b> 
    using concat = typename concat_t<a,b>::type; 

    template <typename a, typename b> 
    struct cartesian1; 

    template <typename a> 
    struct cartesian1<a, list<>> 
    { 
    using type = list<>; 
    }; 

    template <typename a, typename bh, typename... bt> 
    struct cartesian1<a, list<bh, bt...>> 
    { 
    using type = cons<pair<a, bh>, typename cartesian1<a, list<bt...>>::type>; 
    }; 

    template <typename a, typename b> 
    struct cartesian_t; 

    template <typename a> 
    struct cartesian_t<list<>, a> 
    { 
    using type = list<>; 
    }; 

    template <typename ah, typename b, typename... at> 
    struct cartesian_t<list<ah, at...>, b> 
    { 
    using type = concat<typename cartesian1<ah, b>::type, 
         typename cartesian_t<list<at...>, b>::type>; 
    }; 

    template <typename a, typename b> 
    using cartesian = typename cartesian_t<a,b>::type; 

    template <size_t x> 
    struct val {}; 

    template <size_t... a> 
    struct vlist {}; 

    template <typename t> 
    struct vlist2list_t; 

    template <> 
    struct vlist2list_t<vlist<>> 
    { 
    using type = list<>; 
    }; 

    template <size_t ah, size_t... at> 
    struct vlist2list_t<vlist<ah, at...>> 
    { 
    using type = cons<val<ah>, typename vlist2list_t<vlist<at...>>::type>; 
    }; 

    template <typename a> 
    using vlist2list = typename vlist2list_t<a>::type; 

    template <size_t...a> 
    using vl = vlist2list<vlist<a...>>; 

    template<size_t x1, size_t x2> 
    std::ostream& operator<< (std::ostream& s, 
          pair<val<x1>, val<x2>> z) 
    { 
    s << "(" << x1 << "," << x2 << ")"; 
    return s; 
    } 


    std::ostream& operator<< (std::ostream& s, 
          list<> z) 
    { 
    s << "[]"; 
    } 

    template <typename ah, typename... at> 
    std::ostream& operator<< (std::ostream& s, 
          list<ah, at...> z) 
    { 
    s << ah() << ":" << list<at...>(); 
    } 

} 

int main() 
{ 
    using a = ct::cartesian<ct::vl<1,2,3>, ct::vl<4,5,6>>; 
    std::cout << a() << std::endl; 
} 
-1

Désolé pour l'erreur. Je voulais dire:

template<class InIter, class OutIter> 
OutIter cartesian_product(InIter first1, InIter last1, InIter first2, InIter last2, 
OutIter output) { 
for (auto It1 = first1 ; It1 != last1; ++It1) 
    for (auto It2 = first2; It2 != last2; ++It2) 
    *output++ = *It1 * *It2; 
} 
+0

Il est évident que vous n'avez pas testé cela car il ne peut jamais fonctionner comme ça. Après une seule exécution de la boucle interne, 'first2' sera' last2', donc dans toutes les itérations suivantes de la boucle externe, il n'y aura rien à faire. – stefan

+0

Saeed vous devez faire cela dans un métaprogramme modèle. – user1095108

Questions connexes