#include <iostream>
#include <tuple>
#include <typeinfo>
using namespace std;
template <typename PRECISION, int R, int C>
struct Matrix
{
Matrix() {}
};
template <typename DERIVED>
struct VariableTraits
{
// static const int DIM;
};
template <typename DERIVED>
struct WrappedTraits
{
// static const int DIM;
// typedef std::tuple<VARIABLE0, VARIABLE1, ...> VARIABLES;
};
template <int N, typename WRAPPER>
struct WrappedType
{
typedef WrappedTraits<WRAPPER> Traits;
static const int DIM = Traits::DIM;
typedef typename Traits::VARIABLES VARIABLES;
typedef Matrix<float, Traits::DIM, VariableTraits<typename std::tuple_element<N, VARIABLES>::type>::DIM> type;
};
template<int N, typename WRAPPER>
struct MatrixTypeImpl
{
typedef std::tuple<typename MatrixTypeImpl<N - 1, WRAPPER>::type, typename WrappedType<N, WRAPPER>::type> type;
};
template <typename WRAPPER>
struct MatrixTypeImpl<0, WRAPPER>
{
typedef typename WrappedType<0, WRAPPER>::type type;
};
template<typename WRAPPER>
struct MatrixType
{
typedef WrappedTraits<WRAPPER> Traits;
typedef typename MatrixTypeImpl<std::tuple_size<typename Traits::VARIABLES>::value - 1, WRAPPER>::type type;
};
struct FooVariable
{
};
struct BarVariable
{
};
template <>
struct VariableTraits<FooVariable>
{
static const int DIM = 2;
};
template <>
struct VariableTraits<BarVariable>
{
static const int DIM = 3;
};
struct Wrapper
{
};
template <>
struct WrappedTraits<Wrapper>
{
static const int DIM = 2;
typedef std::tuple<FooVariable, BarVariable> VARIABLES;
};
template <int N, typename WRAPPER>
void hello(const typename std::tuple_element<N, typename MatrixType<WRAPPER>::type>::type& mat)
{
}
int main()
{
typedef typename MatrixType<Wrapper>::type MatrixTuple;
Matrix<float, 2, 2> FooMatrix;
Matrix<float, 2, 3> BarMatrix;
// typedef typename std::tuple_element<0, MatrixTuple>::type FooMatrixType;
// typedef typename std::tuple_element<1, MatrixTuple>::type BarMatrixType;
// std::cout << typeid(FooMatrixType).name() << std::endl;
// std::cout << typeid(BarMatrixType).name() << std::endl;
// FooMatrixType FooMatrix;
// BarMatrixType BarMatrix;
hello<0, Wrapper>(FooMatrix);
hello<1, Wrapper>(BarMatrix);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlaW5mbz4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBQUkVDSVNJT04sIGludCBSLCBpbnQgQz4Kc3RydWN0IE1hdHJpeAp7CglNYXRyaXgoKSB7fQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIERFUklWRUQ+CnN0cnVjdCBWYXJpYWJsZVRyYWl0cwp7CiAgICAvLyAgICAgICAgc3RhdGljIGNvbnN0IGludCBESU07Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgREVSSVZFRD4Kc3RydWN0IFdyYXBwZWRUcmFpdHMKewogICAgLy8gICAgICAgIHN0YXRpYyBjb25zdCBpbnQgRElNOwogICAgLy8gICAgICAgIHR5cGVkZWYgc3RkOjp0dXBsZTxWQVJJQUJMRTAsIFZBUklBQkxFMSwgLi4uPiBWQVJJQUJMRVM7Cn07Cgp0ZW1wbGF0ZSA8aW50IE4sIHR5cGVuYW1lIFdSQVBQRVI+CnN0cnVjdCBXcmFwcGVkVHlwZQp7CiAgICB0eXBlZGVmIFdyYXBwZWRUcmFpdHM8V1JBUFBFUj4gVHJhaXRzOwogICAgc3RhdGljIGNvbnN0IGludCBESU0gPSBUcmFpdHM6OkRJTTsKICAgIHR5cGVkZWYgdHlwZW5hbWUgVHJhaXRzOjpWQVJJQUJMRVMgVkFSSUFCTEVTOwogICAgdHlwZWRlZiBNYXRyaXg8ZmxvYXQsIFRyYWl0czo6RElNLCBWYXJpYWJsZVRyYWl0czx0eXBlbmFtZSBzdGQ6OnR1cGxlX2VsZW1lbnQ8TiwgVkFSSUFCTEVTPjo6dHlwZT46OkRJTT4gdHlwZTsKfTsKCnRlbXBsYXRlPGludCBOLCB0eXBlbmFtZSBXUkFQUEVSPgpzdHJ1Y3QgTWF0cml4VHlwZUltcGwKewogICAgdHlwZWRlZiBzdGQ6OnR1cGxlPHR5cGVuYW1lIE1hdHJpeFR5cGVJbXBsPE4gLSAxLCBXUkFQUEVSPjo6dHlwZSwgdHlwZW5hbWUgV3JhcHBlZFR5cGU8TiwgV1JBUFBFUj46OnR5cGU+IHR5cGU7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgV1JBUFBFUj4Kc3RydWN0IE1hdHJpeFR5cGVJbXBsPDAsIFdSQVBQRVI+CnsgICAgIAoJdHlwZWRlZiB0eXBlbmFtZSBXcmFwcGVkVHlwZTwwLCBXUkFQUEVSPjo6dHlwZSB0eXBlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgV1JBUFBFUj4Kc3RydWN0IE1hdHJpeFR5cGUKewogICAgdHlwZWRlZiBXcmFwcGVkVHJhaXRzPFdSQVBQRVI+IFRyYWl0czsKICAgIHR5cGVkZWYgdHlwZW5hbWUgTWF0cml4VHlwZUltcGw8c3RkOjp0dXBsZV9zaXplPHR5cGVuYW1lIFRyYWl0czo6VkFSSUFCTEVTPjo6dmFsdWUgLSAxLCBXUkFQUEVSPjo6dHlwZSB0eXBlOwp9OwoKc3RydWN0IEZvb1ZhcmlhYmxlCnsKfTsKCnN0cnVjdCBCYXJWYXJpYWJsZQp7Cn07Cgp0ZW1wbGF0ZSA8PgpzdHJ1Y3QgVmFyaWFibGVUcmFpdHM8Rm9vVmFyaWFibGU+CnsKICAgIHN0YXRpYyBjb25zdCBpbnQgRElNID0gMjsKfTsKCnRlbXBsYXRlIDw+CnN0cnVjdCBWYXJpYWJsZVRyYWl0czxCYXJWYXJpYWJsZT4KewogICAgc3RhdGljIGNvbnN0IGludCBESU0gPSAzOwp9OwoKc3RydWN0IFdyYXBwZXIKewp9OwoKdGVtcGxhdGUgPD4Kc3RydWN0IFdyYXBwZWRUcmFpdHM8V3JhcHBlcj4KewogICAgc3RhdGljIGNvbnN0IGludCBESU0gPSAyOwogICAgdHlwZWRlZiBzdGQ6OnR1cGxlPEZvb1ZhcmlhYmxlLCBCYXJWYXJpYWJsZT4gVkFSSUFCTEVTOwp9OwoKdGVtcGxhdGUgPGludCBOLCB0eXBlbmFtZSBXUkFQUEVSPgp2b2lkIGhlbGxvKGNvbnN0IHR5cGVuYW1lIHN0ZDo6dHVwbGVfZWxlbWVudDxOLCB0eXBlbmFtZSBNYXRyaXhUeXBlPFdSQVBQRVI+Ojp0eXBlPjo6dHlwZSYgbWF0KQp7CgkKfQoKaW50IG1haW4oKQp7CiAgICB0eXBlZGVmIHR5cGVuYW1lIE1hdHJpeFR5cGU8V3JhcHBlcj46OnR5cGUgTWF0cml4VHVwbGU7CgoJTWF0cml4PGZsb2F0LCAyLCAyPiBGb29NYXRyaXg7CglNYXRyaXg8ZmxvYXQsIDIsIDM+IEJhck1hdHJpeDsKLy8JdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OnR1cGxlX2VsZW1lbnQ8MCwgTWF0cml4VHVwbGU+Ojp0eXBlIEZvb01hdHJpeFR5cGU7Ci8vCXR5cGVkZWYgdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PDEsIE1hdHJpeFR1cGxlPjo6dHlwZSBCYXJNYXRyaXhUeXBlOwovLwlzdGQ6OmNvdXQgPDwgdHlwZWlkKEZvb01hdHJpeFR5cGUpLm5hbWUoKSA8PCBzdGQ6OmVuZGw7Ci8vCXN0ZDo6Y291dCA8PCB0eXBlaWQoQmFyTWF0cml4VHlwZSkubmFtZSgpIDw8IHN0ZDo6ZW5kbDsKCQovLwlGb29NYXRyaXhUeXBlIEZvb01hdHJpeDsKLy8JQmFyTWF0cml4VHlwZSBCYXJNYXRyaXg7CgoJaGVsbG88MCwgV3JhcHBlcj4oRm9vTWF0cml4KTsJCgloZWxsbzwxLCBXcmFwcGVyPihCYXJNYXRyaXgpOwkKCglyZXR1cm4gMDsKfQ==