Using template magic, your problems can be solved by using a variation template and template recursion.
template< size_t N, typename T, typename U, typename... Ts > struct Rows : public Rows<N-1, Ts...> { vector<T> row; U rowinfo; }; template<typename T, typename U> struct Rows<1, T, U> { vector<T> row; U rowinfo; }; Rows< 3, int, string, float, string, double, rss_feed > rows; => struct Rows { vector<int> v1; string s1; vector<foat> v2; string s2; vector<double> v3; rss_feed feed; }
to access the value of this field, you can implement the template function get() member
template< size_t N, typename T, typename U, typename... Ts > struct Rows : public Rows<N-1, Ts...> { vector<T> row; U rowinfo; template< size_t M > typename enable_if< M == N, tuple<vector<T>&, U&> >::type get() { return make_tuple( ref(row), ref(rowinfo) ); } }; template<typename T, typename U> struct Rows<1, T, U> { vector<T> row; U rowinfo; template< size_t M > typename enable_if< M == 1, tuple<vector<T>&, U&> >::type get() { return make_tuple( ref(row), ref(rowinfo) ); } };
Take a moment and digest them. The get() methods return a tuple that contains a link to the request fields, and they are only allowed if the past number matches the class template, but what about the other numbers? ok we can turn them on like this
template< size_t M > typename enable_if< M != N, tuple<vector<T>&, U&> >::type get() { return Rows<N-1, Ts...>::template get<M>();
But it's not right!!! The return type is not tuple<vector<T>&, U&> , it should be tuple<vector<A>&, B&> , where A and B are the corresponding types in the variational pattern Ts...
But how the hell do we get the types that we want from Ts... , we can find out the types of the variation pattern with the following technique.
template< size_t N, typename... Ts > struct variadic_type; template< typename T, typename U, typename... Ts > struct variadic_type< 0, T, U, Ts... > { typedef T T_type; typedef U U_type; }; template< size_t k, typename T, typename U, typename... Ts > struct variadic_type< k, T, U, Ts... > { typedef typename variadic_type< k-1, Ts... >::T_type T_type; typedef typename variadic_type< k-1, Ts... >::U_type U_type; };
therefore variadic_type< 1, int, int, short, short, float, float >::T_type and U_type will be short and short .
Now we have a way to find out the types of a specific place in the variational template, we can apply it to our incorrect get() method to get the correct return type ...
template< size_t M > typename enable_if< M != N, tuple< vector<typename variadic_type< NM, T, U, Ts...>::T_type>&, typename variadic_type< NM, T, U, Ts...>::U_type& > >::type get() { return Rows<N-1, Ts...>::template get<M>(); }
We're done, we can call get() as
Rows< 3, int, string, double, string, float, string > rows; auto r3 = rows.get<3>();
now the index rule is not very nice to deal with, but I think it gives an idea.