Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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 - Fatal编程技术网

C++ 将函数和成员函数都传递给模板方法

C++ 将函数和成员函数都传递给模板方法,c++,templates,C++,Templates,我已经研究这个问题一段时间了,我希望在这里得到一些澄清 我开发了一个模板类。其中一种方法输入两个参数不同的函数,如下所示: template<typename S, typename T, typename R> void TGraph<S,T,R>::BFS(const S &key, bool(*relValid)(R), void(*manip)(string, string, R)) { //Being here R,S members of th

我已经研究这个问题一段时间了,我希望在这里得到一些澄清

我开发了一个模板类。其中一种方法输入两个参数不同的函数,如下所示:

template<typename S, typename T, typename R>
void TGraph<S,T,R>::BFS(const S &key, bool(*relValid)(R), void(*manip)(string, string, R)) {
    //Being here R,S members of the template class TGraph, do stuff including
    if(relValid("some R") ){
    manip("some S", "another S", "someR");
    }

}
模板
void TGraph::BFS(常量S&key,bool(*relValid)(R),void(*manip)(字符串,字符串,R)){
//在这里,R,S模板类TGraph的成员,做一些事情,包括
if(relValid(“某些R”)){
manip(“一些S”,“另一个S”,“一些”);
}
}
当通过main.cpp中的标准函数时,这就像一种魅力

int main(){
    TGraph2<string, User, Relation> graph;
    graph.BFS("Rube", alwaysValid, printRelation);
}
void printRelation(string id1, string id2, Relation rel){
    cout<<id1<<" ha una relazione con "<<id2<<" di tipo "<<rel.type<<endl;
}
bool alwaysValid(Relation rel){
    return true;
}
intmain(){
TGraph2图;
图.BFS(“Rube”,alwaysValid,printRelation);
}
无效打印关系(字符串id1、字符串id2、关系rel){

cout成员函数和非成员函数的调用完全不同。因此,它们不能很好地混合使用。解决此问题的方法是接受函数对象,而不是函数指针或指向成员函数的指针。它们仍然不一定立即接受成员函数,而是接受函数对象完整地实现结果函数可以透明地处理各种函数对象

处理函数对象大致有两种不同的方法:

  • 接受函数对象作为模板参数。这样做对性能很有好处:如果编译器能够看穿调用链,他们会很高兴地内联所有操作(传递lambda函数而不是函数指针,这会非常成功)。此方法的缺点是需要公开函数模板。这取决于可能存在较大问题的上下文。此外,所需的签名在函数签名中不可见,需要在其他位置指定

    您可以按如下方式编写
    BFS()
    成员。使用
    std::invoke()
    可以传递任何可以被视为函数对象的内容,包括成员函数指针和成员指针:

    template<typename S, typename T, typename R, typename RelValid, typename Manip>
    void TGraph<S,T,R>::BFS(const S &key, RelValid relValid, Manip manip) {
        //Being here R,S members of the template class TGraph, do stuff including
        if(std::invoke(relValid, "some R") ){
            std::invoke(manip, "some S", "another S", "someR");
        }
    }
    
    模板
    void TGraph::BFS(常量S&key、RelValid、Manip Manip){
    //在这里,R,S模板类TGraph的成员,做一些事情,包括
    if(std::invoke(relValid,“some R”)){
    调用(manip,“some S”,“other S”,“someR”);
    }
    }
    
  • 接受仅指定函数接口的类型擦除函数对象。
    std::function
    显然是类型擦除函数对象的首选。函数指针、成员函数指针和函数对象通常很容易转换为兼容的
    std::function
    类型

    使用
    std::function
    替换函数指针是直截了当的:函数指针已经使用了签名,该签名是
    std::function
    所需的模板参数:

    模板
    void TGraph::BFS(常量S&key,std::函数relValid,std::函数manip){
    //在这里,R,S模板类TGraph的成员,做一些事情,包括
    if(relValid(“某些R”)){
    manip(“一些S”,“另一个S”,“一些”);
    }
    }
    

  • 选择哪种方法在某种程度上取决于预期用途。如果函数对象被大量使用,例如,对访问的每个节点调用一次,我更喜欢使用模板参数。如果函数只使用了几次或需要在非模板化界面中显示,我会使用
    std::function
    (或类似).

    听起来像是函数包装器的工作。如果您使用的是C++11和您可以使用的实用程序库,或者您可以自己编写。如果您可以使用C++17,请看一下
    std::invoke
    ,它以一种非常方便的方式处理自由函数、lambda和指向成员函数的指针。@Beta我可以使用std::function,但我想不出是什么w将成员函数绑定到模板类中的std::function方法。谢谢你,我必须使用c++11,我将尝试使用std::function方法。我按照你的建议编辑了BSF,但我不知道如何传递成员函数。如果我正确调用c++11
    std::function
    没有执行
    std::invoke(…)
    -dance,即,您需要
    std::mem\u fn(&C::fun)
    。请注意,成员函数的第一个参数是要调用成员函数的对象(this
    指向的ibject)。因此,您很可能希望传递类似
    std::bind(&C::mem,&object,std::placeholder::\u 1)
    template<typename S, typename T, typename R, typename RelValid, typename Manip>
    void TGraph<S,T,R>::BFS(const S &key, RelValid relValid, Manip manip) {
        //Being here R,S members of the template class TGraph, do stuff including
        if(std::invoke(relValid, "some R") ){
            std::invoke(manip, "some S", "another S", "someR");
        }
    }
    
    template<typename S, typename T, typename R>
    void TGraph<S,T,R>::BFS(const S &key, std::function<bool(R)> relValid, std::function<void(string, string, R)> manip) {
        //Being here R,S members of the template class TGraph, do stuff including
        if(relValid("some R") ){
            manip("some S", "another S", "someR");
        }
    }