dimanche 25 janvier 2015

Static Recursive Tuple

I am hoping to be able to statically create a tuple by recursively wrapping another tuple with some extra type information.


A simple example would be :



std::tuple<int, float> MyTuple;
std::tuple<Matrix<int, 2, 3>, Matrix<float, 4, 5>> WrappedMyTuple;


Here is the full example of the code I have implemented to try and achieve this wrapping (Apologies as the implementation I am presenting is obfuscated by the details of the code-base I yanked it from.):



#include <iostream>
#include <tuple>
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 WrappedType<N, WRAPPER>::type, typename MatrixTypeImpl<N - 1, 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 MatrixTypeImpl<std::tuple_size<typename Traits::VARIABLES>::value - 1, WRAPPER> 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 WrappedTraits<Wrapper> Traits;
typedef typename Traits::VARIABLES VARIABLES;
typedef typename MatrixType<Wrapper>::type MatrixTuple;

Matrix<float, 2, 2> FooMatrix;
Matrix<float, 2, 3> BarMatrix;

hello<0, Wrapper>(FooMatrix);
hello<1, Wrapper>(BarMatrix);

return 0;
}


ideone link


This will not compile since because it was not able to deduce the template arguments :



prog.cpp: In function 'int main()':
prog.cpp:98:29: error: no matching function for call to 'hello(Matrix<float, 2, 2>&)'
hello<1, Wrapper>(FooMatrix);
^
prog.cpp:98:29: note: candidate is:
prog.cpp:84:6: note: template<int N, class WRAPPER> void hello(const typename std::tuple_element<N, typename MatrixType<WRAPPER>::type>::type&)
void hello(const typename std::tuple_element<N, typename MatrixType<WRAPPER>::type>::type& mat)
^
prog.cpp:84:6: note: template argument deduction/substitution failed:
prog.cpp: In substitution of 'template<int N, class WRAPPER> void hello(const typename std::tuple_element<N, typename MatrixType<WRAPPER>::type>::type&) [with int N = 1; WRAPPER = Wrapper]':
prog.cpp:98:29: required from here
prog.cpp:84:6: error: invalid use of incomplete type 'struct std::tuple_element<1u, MatrixTypeImpl<1, Wrapper> >'
In file included from /usr/include/c++/4.9/tuple:38:0,
from prog.cpp:2:
/usr/include/c++/4.9/utility:85:11: error: declaration of 'struct std::tuple_element<1u, MatrixTypeImpl<1, Wrapper> >'
class tuple_element;
^


Anyone got a better idea how to achieve this wrap or a way to fix the current attempt?


Seems like it should not be that hard.


Aucun commentaire:

Enregistrer un commentaire