2013-08-12 4 views
3

인기있는 indices trick의 변형이 필요합니다. 길이가 서로 다른 인덱스의 2 시퀀스의 데카르트 곱을 계산합니다. 이것이 어떻게 수행 될 수 있는지에 대한 힌트/예제를 줄 수 있습니까? 라이브러리에 대한 링크 일 수도 있습니다.데카르트 곱 인덱스 생성기

편집 : 난 단지이 함께 올 수 : 실수에 대한

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

최종 시퀀스가 ​​어떻게 보이겠습니까? 인덱스 쌍 목록? 또한, 아직 시도한 것은 무엇입니까? 정규 벡터 /리스트에 대해 카티 션 곱이 어떻게 수행되고 TMP까지 포팅 하는지를 볼 수 있어야합니다. – Xeo

+0

나는 무언가 일 수 있던 쌍의 표현을 남겨두고, 균등 한 크기의 단일 순서로 '평탄화'될 수 있었다. 나중에 시도해 보도록하겠습니다. 너무 힘들지는 않을 것입니다.하지만 누군가는 오래 전에 작성된 일부 코드를 복사하여 붙여 넣을 수도 있습니다. :) – user1095108

답변

4

입니다.

#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

죄송합니다. 나는 의미 : 다음은 오히려 간단하고 지루한 구현

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

이렇게 테스트 해 보지 않은 것은 분명합니다. 내부 루프를 한 번 실행 한 후에'first2'는'last2'가 될 것이므로 외부 루프의 모든 후속 반복에서 아무 것도 할 수 없습니다. – stefan

+0

이 작업을 템플릿 메타 프로그램으로 만들어야합니다. – user1095108

관련 문제