Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

c++ - "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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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...> {};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...