I'd like to create the cross product of a list of types using variadic templates.
Here's what I have so far:
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
template<typename...> struct type_list {};
template<typename T1, typename T2> struct type_pair {};
template<typename T, typename... Rest>
struct row
{
typedef type_list<type_pair<T,Rest>...> type;
};
template<typename... T>
struct cross_product
{
typedef type_list<typename row<T,T...>::type...> type;
};
int main()
{
int s;
typedef cross_product<int, float, short>::type result;
std::cout << abi::__cxa_demangle(typeid(result).name(), 0, 0, &s) << std::endl;
return 0;
}
This program outputs:
$ g++ -std=c++0x cross_product.cpp ; ./a.out
type_list<type_list<type_pair<int, int>, type_pair<int, float>, type_pair<int, short> >, type_list<type_pair<float, int>, type_pair<float, float>, type_pair<float, short> >, type_list<type_pair<short, int>, type_pair<short, float>, type_pair<short, short> > >
But I'd like it to output:
type_list<type_pair<int,int>, type_pair<int,float>, type_pair<int,short>, type_pair<float,int>,...>
That is, without the nested type_list
s.
Is there a direct way to do this without the row
helper, or should the solution "unwrap" the nested type_list
s somehow?
So far all solutions have drawbacks, unnecessary dependencies, unnecessary helpers and all are restricted to the Cartesian power of two. The following solution has no such drawbacks and supports:
It was actually to harder to implement (but good as homework) then I thought. I am actually thinking about creating a little generator which allows me an extended template syntax which makes these things really easy.
Simplified the code works as follows:
product
converts an input listtuple<A...>,tuple<B...>,tuple<C...>
intotuple<tuple<A>...>, tuple<B...>, tuple<C...>
. This second list is then passed toproduct_helper
which does the recursive Cartesian product computation.Here is a compilable example of how the code can be used.