Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Unpack" an array to call a function with variadic template

I'm using the ben strasser C++ fast csv parser: https://github.com/ben-strasser/fast-cpp-csv-parser. It uses a variadic template to pass column values back to the while loop that processes the csv data:

io::CSVReader<2> in(csv_filename);
double x, y;
while(in.read_row(x,y)) {
    //code with x and y
}

This calls the following function in the CSVReader class:

template<class ...ColType>
bool read_row(ColType& ...cols){
    //snip
}

This works fine for me with my x and y values. However, I would like to expand this to use arbitrary dimensions. This means my data has a (known) number of columns I need to read. I would like to use something like this:

io::CSVReader<known_dimension> in(csvfname);
double data[known_dimension];
while(in.read_row(data)) {
    //code with data[0],data[1],...,data[known_number]
}

However, this is not valid syntax. I need to "unpack" the array of doubles into separate arguments of pointers to my doubles. I'd like to do this without modifications to the fast csv parser.

like image 550
Thijs Miedema Avatar asked Feb 07 '23 23:02

Thijs Miedema


1 Answers

You can use std::integer_sequence for that purpose:

namespace Detail
{
template <typename Reader, typename T, std::size_t... I>
void read_row(Reader& in, T* data, std::index_sequence<I...>)
{
     in.read_row(data[I]...); // A trick here
} 

}

template <std::size_t N, typename T>
void read_row(io::CSVReader<N>& in, T* data)
{
     Detail::read_row(in, data, std::make_index_sequence<N>{});
} 

And of course, use like this:

int a[7];
io::CSVReader<7> r;
read_row(r, a);

"Working" example: link


For compiler "below" C++14 - integer_sequence (actually just index_sequence needed) is pretty easy to implement:

template <std::size_t... I>
class index_sequence {};

And make_index_sequence not so easy - but also doable:

template <std::size_t N, std::size_t ...I>
struct make_index_sequence : make_index_sequence<N-1, N-1,I...> {};

template <std::size_t ...I>
struct make_index_sequence<0,I...> : index_sequence<I...> {};
like image 148
PiotrNycz Avatar answered Feb 13 '23 16:02

PiotrNycz