У меня есть несколько файлов с разделенными пробелами данными. Я хочу функцию parse
, которая принимает только имя файла и функцию, которая действует на все элементы в одной строке. Например, если у меня есть файл с данными в формате
int float string
int float string
int float string
...
тогда я хочу иметь функцию parse
, которая принимает имя файла, содержащего эти данные, а также лямбду, которая будет обрабатывать каждую строку. Если бы я знал, сколько элементов было в каждой строке (в данном случае 3), то я мог бы сделать это:
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
template <typename Func, typename A, typename B, typename C>
void parse(const string & filename, Func func){
string line;
// TODO: Get line from file, not cin
// std::ifstream file(filename);
while (std::getline(cin, line)) {
stringstream ss(line);
A a;
B b;
C c;
ss >> a >> b >> c;
func( a, b, c );
}
}
int main()
{
auto forEach = [](int a, float b, string c){ cout << a << "," << b << "," << c << endl; };
parse<decltype(forEach),int,float,string>( "test.txt", forEach );
return 0;
}
Приведенный выше код не зависит от типов аргументов, но требует ровно 3 значения в каждой строке. Я хотел бы помочь в расширении этого до версии, где число аргументов в строке либо
- выведено из типа
Func
(это был бы идеальный сценарий).
- указан как пакет параметров шаблона.
Например, я бы изобразил случай 1, похожий на
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
template <typename Func>
void parse(const string & filename, Func func){
string line;
// TODO: Get line from file, not cin
// std::ifstream file(filename);
while (std::getline(cin, line)) {
stringstream ss(line);
// TODO Infer from the type Func that it requires
// int, float, string
// Then use a stringstream to parse those values from `line`
// and pass the results to func
func( ... );
}
}
int main()
{
auto forEach = [](int a, float b, string c){ cout << a << "," << b << "," << c << endl; };
parse<decltype(forEach)>( "test.txt", forEach );
return 0;
}
Если это невозможно, я бы принял решение, используя пакет параметров. Я просто не понимаю, как это сделать. Я полагаю, что решение будет выглядеть так:
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
template <typename Func, typename ...Args>
void parse(const string & filename, Func func){
string line;
// TODO: Get line from file, not cin
// std::ifstream file(filename);
while (std::getline(cin, line)) {
stringstream ss(line);
// TODO: Use Args to extract parse the appropriate number of
// parameters from `line` and pass the result to `func`
func( ... );
}
}
int main()
{
auto forEach = [](int a, float b, string c){ cout << a << "," << b << "," << c << endl; };
parse<decltype(forEach),int,float,string>( "test.txt", forEach );
return 0;
}