Преобразование параметров вариационного шаблона в другие типы
Как преобразовать типы из параметров вариационного шаблона в другой тип?
Например:
template <typename... T>
struct single
{
std::tuple<T...> m_single;
};
template <typename... T>
struct sequences
{
single<T...> get(size_t pos)
{
// I don't know how to convert here
return std::make_tuple(std::get<0>(m_sequences)[pos]... std::get<N>(m_sequences)[pos]);
}
template <size_t Idx>
std::vector<
typename std::tuple_element<Idx, std::tuple<T...>>::type
>
get_sequence()
{
return std::get<Idx>(m_sequences);
}
std::tuple<T...> m_sequences; // std::tuple<std::vector<T...>> I don't know how to conver here
};
Я хочу написать так:
sequences<int, double, double> seq;
single<int, double, double> sin = seq.get(10);
И имеют std::tuple<std::vector<int>, std::vector<double>, std::vector<double>>
в структурных последовательностях. И получить один от него.
std::vector<single<T...>>
- плохая идея для меня, потому что мне нужна полная последовательность, и ее легко скопировать.
Возможно ли это?
Большое спасибо. Извините за мой плохой английский.
Ответы
Ответ 1
Вы можете сделать больше, чем просто расширить пакет переменных параметров в виде простого списка: вы можете также расширить выражение. Поэтому вы можете m_sequences
быть кортежем векторов, а не кортежем элементов:
template <typename... T>
struct sequences
{
std::tuple<std::vector<T>...> m_sequences;
};
Вы также можете сделать отличные трюки с пакетами параметров, чтобы выбрать соответствующий элемент из вектора:
template<size_t ... Indices> struct indices_holder
{};
template<size_t index_to_add,typename Indices=indices_holder<> >
struct make_indices_impl;
template<size_t index_to_add,size_t...existing_indices>
struct make_indices_impl<index_to_add,indices_holder<existing_indices...> >
{
typedef typename make_indices_impl<
index_to_add-1,
indices_holder<index_to_add-1,existing_indices...> >::type type;
};
template<size_t... existing_indices>
struct make_indices_impl<0,indices_holder<existing_indices...> >
{
typedef indices_holder<existing_indices...> type;
};
template<size_t max_index>
typename make_indices_impl<max_index>::type make_indices()
{
return typename make_indices_impl<max_index>::type();
}
template <typename... T>
struct sequences
{
std::tuple<std::vector<T>...> m_sequences;
template<size_t... Indices>
std::tuple<T...> get_impl(size_t pos,indices_holder<Indices...>)
{
return std::make_tuple(std::get<Indices>(m_sequences)[pos]...);
}
std::tuple<T...> get(size_t pos)
{
return get_impl(pos,make_indices<sizeof...(T)>());
}
};
Ответ 2
ОК, это может показаться немного переполненным, но как насчет этого: насколько я знаю, единственным вариантом "итерации" вариаторов является использование нотации <head, tail...>
с помощью специализированной шаблона для простого случая <head-only>
.
Поэтому вы можете попробовать что-то вроде этого:
простой случай:
template <typename T>
struct sequences
{
std::tuple<T> get(size_t pos)
{
return values[pos];
}
std::vector<T> get_sequence()
{
return values;
}
std::vector<T> values;
};
рекурсивный случай:
template <typename T, typename ...U>
struct sequences
{
std::tuple<T, std::tuple<U...> > get(size_t pos)
{
return std::make_tuple(values[pos], remainder->get(pos));
}
template <size_t Idx>
std::vector<
typename std::tuple_element<Idx, std::tuple<T...>>::type
> get_sequence()
{
return get_sequence_internal<
typename std::tuple_element<Idx, std::tuple<T...>>::type, Idx
>();
}
template <typename V, 0>
std::vector<V> get_sequence_internal()
{
return values;
}
template <typename V, size_t Idx>
std::vector<V> get_sequence()
{
return remainder->getSequence_internal<V, Idx-1>();
}
std::vector<T> values;
sequences<U...>* remainder;
};
Отказ от ответственности: не проверен, даже не составлен, но я предполагаю, что вы получите основную идею. По крайней мере остаются две проблемы:
- Возвращаемое значение
get()
- это не ваша единственная структура, а цепочка кортежей. Возможно, вы можете развязать его рекурсивно с помощью std::get<0>
...
- Я не знаю, генерирует ли специализация get_sequence_internal ошибку времени компиляции, потому что тип
V
может отличаться от T
.