4

我有一个带有参数包的模板函数。我想将其扩展为对第二个函数的调用,同时还提供 pack 中项目的索引。我可能可以弄清楚如何用递归来做,但我想尝试用折叠表达式来做。

这是我希望参数包扩展成的功能

template<typename T>
void addToRecord(Record& rec, int idx, T&& val)
{
    // Do some stuff.
}

这是接受参数包的函数

template<typename... ARGS>
void addRecord(ARGS&& ...values)
{
    Record rec;
    // addToRecord(rec, ??????)  How do expand 'values' here addToRecord with index of each item?
}

这可能吗?我意识到这并不重要,但我也在尝试更好地使用折叠表达式。

4

3 回答 3

5

您可以编写一个辅助函数,该函数采用编译时整数序列以及值

template<typename... Args, std::size_t... Is>
void addRecord_impl(Record& rec, std::index_sequence<Is...>, Args && ...values)
{
    (addToRecord(rec, Is, std::forward<Args>(values)), ...);  // Is and values will be expanded in lock step
}

然后像这样调用这个助手

template<typename... Args>
void addRecord(Args && ...values)
{
    Record rec;
    addRecord_impl(rec, 
                   std::index_sequence_for<Args...>{}, 
                   std::forward<Args>(values)...);
}

这是一个演示

于 2021-09-02T01:59:52.877 回答
3

除了另一个答案,让我提一个不需要辅助函数的更简单的方法:

template<typename... Args>
void addRecord(Args&&... values) {
    Record rec;

    int i = 0;
    (addToRecord(rec, i++, std::forward<Args>(values)), ...);
}

逗号操作符, 保证所有addToRecord()的 s 都会被按顺序调用:

在逗号表达式E1, E2中,表达式E1被求值,它的结果被丢弃,并且它的副作用在表达式的求值E2开始之前完成。

于 2021-09-02T06:29:42.617 回答
1

当我需要这样做时,我喜欢内联。

template<std::size_t...Is>
auto indexer_over( std::index_sequence<Is...> ) {
  return [](auto&& f)->decltype(auto){
    return f( std::integral_constant<std::size_t, Is>{}... );
  };
}
template<std::size_t N, class F>
auto index_upto( F&& f ) {
  return indexer_over(std::make_index_sequence<N>{})(std::forward<F>(f));
}

那么你的代码是:

template<typename... ARGS>
void addRecord(ARGS&& ...values)
{
  Record rec;
  index_upto<sizeof...(ARGS)>( [&](auto...Is) {
    ( addToRecord(rec, Is), ... );
  } );
}

与@evg 的解决方案相比,这具有优势,即Is每次调用的编译时间常量addToRecord,如果这很重要的话。

Is中,您可以在没有帮助程序的情况下获得值的编译时集合。

[&]<std::size_t...Is>(std::index_sequence<Is...>) {
  ( addToRecord(rec,Is), ... );
}( std::make_index_sequence<sizeof...(ARGS)>{} );
于 2021-09-03T15:51:44.487 回答