c++ 在编译时获取可变参数模板的索引和值

nhhxz33t  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(120)

我有一个函数,看起来像这样

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表示postgres结果表的一行,支持取列值为res[0].as<int>()
问题是我不知道如何扩展可变参数模板参数来访问类型索引和类型本身。我应该用什么来代替???

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


我试图定义int i = 0并像res[i++].as<Rets>()...一样扩展,但编译器给出警告

Multiple unsequenced modifications to 'i'


所以也许有一些更好的方法来扩展return语句,比如下面的例子,没有运行时变量

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

ryhaxcpt

ryhaxcpt1#

您想要为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...);
}

字符串

dkqlctbz

dkqlctbz2#

从C++20开始,lambda表达式可以有一个显式的模板参数列表。在定义之后立即调用lambda已经成为一种普遍的现代习惯。这两种思想的结合在可变参数模板编程中非常常见。但与以往一样,主要规则是包扩展表达式中的所有参数包都被扩展在一起,并且需要具有相同的大小:

return [&res] <std::size_t ... i>
       (std::index_sequence<i...>) {
       return std::tuple{ res[i].as<Rets>()... };
} (std::index_sequence_for<Rets...>{});

字符串
注意,在内部return语句中,iRets同时展开。
在上面的代码中,我使用了C20的C20语法来缩短代码序列;这就是为什么tuple后面没有<Rets...>。在这种情况下,显式参数列表通常用于转换,或者当类参数不能完全从构造函数参数推导出来时。

相关问题