Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用模板参数包分析一行文本_C++_Templates_Variadic Templates - Fatal编程技术网

C++ 使用模板参数包分析一行文本

C++ 使用模板参数包分析一行文本,c++,templates,variadic-templates,C++,Templates,Variadic Templates,我有一些带有空格分隔数据的文件。我想要一个函数parse,它只接受一个文件名和一个作用于一行中所有元素的函数。例如,如果我有一个文件,它的数据格式是 int float string int float string int float string ... 然后我想要一个函数parse,它接受包含此数据的文件名,以及一个lambda,它将处理每一行。如果我知道每条线上有多少个元素(在本例中为3),那么我可以这样做: #include <fstream> #include <

我有一些带有空格分隔数据的文件。我想要一个函数
parse
,它只接受一个文件名和一个作用于一行中所有元素的函数。例如,如果我有一个文件,它的数据格式是

int float string
int float string
int float string
...
然后我想要一个函数
parse
,它接受包含此数据的文件名,以及一个lambda,它将处理每一行。如果我知道每条线上有多少个元素(在本例中为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;
}
如果不可能,那么我会接受使用参数包的解决方案。我就是不知道该怎么做。我认为解决方案是这样的:

#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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
模板
无效解析(常量字符串和文件名,Func Func){
弦线;
//TODO:从文件中获取行,而不是cin
//std::ifstream文件(文件名);
while(std::getline(cin,line)){
弦流ss(线);
//TODO:使用Args提取并解析适当数量的
//参数,并将结果传递给“func”`
func(…);
}
}
int main()
{

auto-forEach=[](int a、float b、string c){cout函数特性可以通过
操作符()或函数指针找到(无重载)

template<typename C> struct function_trait : function_trait<decltype(&C::operator())> {};

template <typename C, typename Ret, typename...Args>
struct function_trait<Ret (C::*)(Args...) const> : function_trait<Ret(Args...)> {};
// Handle volatile, reference on this, C-ellipsis combination... 
template <typename Ret, typename...Args>
struct function_trait<Ret (*)(Args...)> : function_trait<Ret(Args...)> {};

template <typename Ret, typename...Args>
struct function_trait<Ret (Args...)>
{
    using args = std::tuple<Args...>;
};
因此,请替换:

parse(is, func, typename function_trait<Func>::args{});
parse(is,func,typename函数_trait::args{});

parse(is,func,typename tuple_detaction::type{});

这通常是使用递归完成的,其中每个递归调用读取一个值。还要注意,“字符串”实际上是一个宽泛的术语,如果要处理包含空格的字符串,则应使用
std::getline
读取最后一个数据。虽然这看起来几乎是正确的想法,但似乎有很多拼写错误(typename应该是第一个代码块中的模板,等等)。我无法编译这段代码。我将不得不使用它来看看是否能正常工作。它似乎至少需要C++17。@不莱梅•马特:是的,提供的代码使用C++17(更简单,更不冗长),但可以在C++11/C++14中完成。我希望C++11版本能够在我拥有的一些嵌入式硬件上工作。但我怀疑您能否在C++11中获得所需的所有函数信息。这很快。我稍后会检查它。
template <typename Func, typename Tuple>
void parse(std::istream& is, Func func, Tuple t)
{
    std::string line;
    while (std::getline(is, line)) {
        std::stringstream ss(line);
        std::apply([&ss](auto&... args){ ((ss >> args), ...);}, t);
        std::apply(func, t);
    }
}

template <typename Func>
void parse(std::istream& is, Func func)
{
    parse(is, func, typename function_trait<Func>::args{});
}
auto forEach = [](int a, float b, string c){ cout << a << "," << b << "," << c << endl; }; 
parse(std::cin, forEach );
template <typename T> struct tuple_decay;
template <typename... Ts> struct tuple_decay<std::tuple<Ts...>>
{
    using type = std::tuple<std::decay_t<Ts>...>;
};
parse(is, func, typename function_trait<Func>::args{});
parse(is, func, typename tuple_decay<typename function_trait<Func>::args>::type{});