将数组的值作为参数解包为可变参数函数

Jdl*_*lCR 5 c++ template-meta-programming variadic-templates c++11 c++14

我正在尝试(在编译时)将整数解包为可变参数函数的参数.想法是std::index_sequence在编译时将这些值打包在数组或(c ++ 14)中.我试图使用较旧帖子中的一些答案,但我发现示例代码对于我的级别是不可读的.

这是一个简单的示例,其中包含我需要在我正在编写的代码中实现的功能,在这种情况下尝试使用std::make_index_sequence.我不一定需要使用后者.问题是序列的值不会作为variadic函数的参数解压缩:

#include <cstdio>
#include <iostream>
#include <utility>

using namespace std;


void print(const int &val){
  cout << val << endl;
}

template<typename ...S> void print(const int &val, const S&... others)
{
  print(val);
  print(others...);
}

template<size_t n> void printNumbers(){
  std::make_index_sequence<n> a;
  print(a);
}


int main(){
  printNumbers<6>();
}
Run Code Online (Sandbox Code Playgroud)

GCC8的输出:

    tet.cc: In instantiation of ‘void printNumbers() [with long unsigned int n = 6]’:
tet.cc:25:19:   required from here
tet.cc:20:8: error: no matching function for call to ‘print(std::make_index_sequence<6>&)’
   print(a);
   ~~~~~^~~
tet.cc:8:6: note: candidate: ‘void print(const int&)’
    void print(const int &val){
     ^~~~~
tet.cc:8:6: note:   no known conversion for argument 1 from ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’} to ‘const int&’
tet.cc:12:30: note: candidate: ‘template<class ... S> void print(const int&, const S& ...)’
template<typename ...S> void print(const int &val, const S&... others)
                                 ^~~~~
tet.cc:12:30: note:   template argument deduction/substitution failed:
tet.cc:20:9: note:   cannot convert ‘a’ (type ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’}) to type ‘const int&’
Run Code Online (Sandbox Code Playgroud)

Pio*_*cki 6

std::make_index_sequence<6>是以下的别名:

std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
Run Code Online (Sandbox Code Playgroud)

a这是作为函数调用参数的表达式的类型print(a)。您的print函数需要单独的值,而不是std::integer_sequence.

为了使您的实现工作,您应该首先推导索引,然后才将它们用作以下参数print

template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
    print(Is...);
}

template <std::size_t N>
void printNumbers()
{
    printNumbers(std::make_index_sequence<N>{});
}
Run Code Online (Sandbox Code Playgroud)

中,您可以删除中间print函数并只说:

template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
    (print(Is), ...);
}
Run Code Online (Sandbox Code Playgroud)

中,您可以在单个函数中创建索引序列并推导其索引:

template <std::size_t N>
void printNumbers()
{
    [] <std::size_t... Is> (std::index_sequence<Is...>)
    { (print(Is), ...); }(std::make_index_sequence<N>{});
}
Run Code Online (Sandbox Code Playgroud)

演示版