我需要一个流行的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 :(得分: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 :(得分:-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;
}