Вы используете C ++ 14, поэтому вы можете использовать std::index_sequence
/ std::make_index_sequence
/ std::index_sequence_for
...
Я предлагаю вызвать product()
, передав сначала функцию, а затем векторы.
Я имею в виду
product([=](int i, double j, int k) { process(i, j, k); }, iv, jv, kv);
Таким образом, вы можете использовать переменные шаблоны для векторов.
Предлагаю также следующие вспомогательные функции
template <typename F, std::size_t ... Is, typename Tp>
void productH (F f, std::index_sequence<Is...> const &, Tp const & tp)
{ f(std::get<Is>(tp)...); }
template <typename F, typename Is, typename Tp, typename T0, typename ... Ts>
void productH (F f, Is const & is, Tp const & tp, T0 const & t0, Ts ... ts)
{
for ( auto const & val : t0 )
productH(f, is, std::tuple_cat(tp, std::tie(val)), ts...);
}
так product()
просто станет
template <typename F, typename ... Ts>
void product (F f, Ts ... ts)
{ productH(f, std::index_sequence_for<Ts...>{}, std::make_tuple(), ts...); }
Идея заключается в извлечении и накоплении в std::tuple
значений. Учитывая окончательное значение std::tuple
, вызовите функцию, извлекающую значения из std::tuple
с использованием std::get
и индексы, сгенерированные с помощью std::index_sequence_for
.
Заметьте, что нет необходимости, чтобы вектор был std::vector
с; может быть std::queue
, std::array
и т. д.
Ниже приведен полный пример компиляции
#include <array>
#include <tuple>
#include <deque>
#include <vector>
#include <utility>
#include <iostream>
template <typename F, std::size_t ... Is, typename Tp>
void productH (F f, std::index_sequence<Is...> const &, Tp const & tp)
{ f(std::get<Is>(tp)...); }
template <typename F, typename Is, typename Tp, typename T0, typename ... Ts>
void productH (F f, Is const & is, Tp const & tp, T0 const & t0, Ts ... ts)
{
for ( auto const & val : t0 )
productH(f, is, std::tuple_cat(tp, std::tie(val)), ts...);
}
template <typename F, typename ... Ts>
void product (F f, Ts ... ts)
{ productH(f, std::index_sequence_for<Ts...>{}, std::make_tuple(), ts...); }
void process (int i1, double d1, int i2)
{ std::cout << '[' << i1 << ',' << d1 << ',' << i2 << ']' << std::endl; }
int main ()
{
std::vector<int> iv = { 1, 2, 3, 4 };
std::array<double, 4u> jv = { { .5, 1., 1.5, 2. } };
std::deque<int> kv = { 5, 4, 3, 2 };
product([=](int i, double j, int k) { process(i, j, k); }, iv, jv, kv);
}
К сожалению, вы не можете использовать C ++ 17, где вы можете избежать std::index_sequence
/ std::index_sequence_for
/ std::get()
и использовать std::apply()
следующим образом
template <typename F, typename Tp>
void productH (F f, Tp const & tp)
{ std::apply(f, tp); }
template <typename F, typename Tp, typename T0, typename ... Ts>
void productH (F f, Tp const & tp, T0 const & t0, Ts ... ts)
{
for ( auto const & val : t0 )
productH(f, std::tuple_cat(tp, std::tie(val)), ts...);
}
template <typename F, typename ... Ts>
void product (F f, Ts ... ts)
{ productH(f, std::make_tuple(), ts...); }