В качестве детского примера вы можете представить себе что-то вроде этого - просто кортеж одного фиксированного типа на данный момент:
template <int N> struct MyTuple : MyTuple<N - 1>
{
T data;
};
template <> struct MyTuple<0> { };
Реальное решение, конечно, будет иметь параметры шаблонов с переменными параметрами для типов данных.и также предоставил бы конструктор с переменными координатами, создающий data
с первым элементом и передающий оставшиеся элементы базовому конструктору.
Теперь мы можем попытаться получить доступ к i
th элементу:
template <int K> struct get_impl
{
template <int N> static T & get(MyTuple<N> & t)
{
return get_impl<K - 1>::get(static_cast<MyTuple<N - 1>&>(t));
}
};
template <> struct get_impl<0>
{
template <int N> static T & get(MyTuple<N> & t)
{
return t.data;
}
};
Ключевым моментом здесь является наличие специализации при K = 0
, которая извлекает фактический элемент, и создание иерархии наследования, пока вы не окажетесь там.Наконец, мы снимаем вывод типа кортежа через шаблон функции:
template <int K, int N> T & get(MyTuple<N> & t)
{
return get_impl<K>::get(t);
}