c++templatesc++17variadic-templateslibpqxx

Get index and value of variadic template at compile time


I have a function that looks like this

template <typename... Rets, typename... Args>
std::tuple<Rets...> call_nn(std::string_view query, Args... args)
{
  pqxx::work w(con_);
  pqxx::row res = w.exec_params1(pqxx::zview(query), args...);
  w.commit();
  return // std::tuple<Rets...>((res[std::index_sequence_for<Rets>{}].as<Rets>())...); doesn't work
}

pqxx::row represents one row of result table from postgres. It supports getting column value as res[0].as<int>().

The problem is that I don't know how to expand the variadic template argument to access the type index and the type itself. What should I put instead of ????

return std::tuple(ret[/*???*/].as<Rets>()...);

I tried to define int i = 0 and expand like res[i++].as<Rets>()... but then compiler gives warning

Multiple unsequenced modifications to 'i'

so maybe there are some better ways to expand return statement to something like example below without runtime variables

return std::tuple(ret[0].as<X>(), ret[1].as<Y>(), /*...*/ ret[n].as<Z>() );

Solution

  • You want to create a second parameter pack for the values in index_sequence:

    template <typename... Rets, std::size_t... Idxs, typename... Args>
    std::tuple<Rets...> call_nn(std::index_sequence<Idxs...>, std::string_view query, Args&... args)
    {
      pqxx::work w(con_);
      pqxx::row res = w.exec_params1(pqxx::zview(query), args...);
      w.commit();
      return std::tuple<Rets...>((res[Idxs].as<Rets>())...);
    }
    
    template <typename... Rets, typename... Args>
    std::tuple<Rets...> call_nn(std::string_view query, Args... args)
    {
        return call_nn<Rets...>(std::index_sequence_for<Rets...>{}, query, args...);
    }