简体   繁体   English

将模板 function 传递给 std::bind?

[英]Pass template function to std::bind?

I want to use std::bind with template function. Is it somehow possible?我想将 std::bind 与模板 function 一起使用。这有可能吗?

PS It is IMPORTANT to use std::bind , because I know at least one solution through lambdas and want to find out if there is std::bind solution. PS 使用std::bind很重要,因为我至少知道一个通过 lambdas 的解决方案,想知道是否有 std::bind 解决方案。

#include <iostream>
#include <functional>
#include <memory>

using namespace std;

struct foo : std::enable_shared_from_this<foo>
{
    void f()
    {
        // doesn't compile, error : no matching function for call to 'bind'
        auto cb = std::bind(&foo::handle, shared_from_this(), placeholders::_1, placeholders::_2);
    }

    template <typename T, typename U>
    void handle(T, U)
    {
    }
};

int main()
{
    return 0;
}

handle is not a template function. There are no "template functions". handle不是模板 function。没有“模板函数”。 handle is a function template, ie it is a template, it is not a function. You cannot std::bind to a template. handle是一个 function 模板,即它是一个模板,它不是 function。你不能std::bind到一个模板。 You can only std::bind to a callable.您只能std::bind到可调用对象。

The trick is to defer instantiation of the template and deduction of the template parameters to when the function is actually called:诀窍是将模板的实例化和模板参数的推导推迟到实际调用 function 时:

#include <iostream>
#include <functional>
#include <memory>

using namespace std;

struct foo {

    struct handle_caller {
        template <typename T,typename U>
        void operator()(foo* f, T t,U u){
            f->handle(t,u);
        }
    };

    void f()
    {
        auto cb = std::bind(handle_caller{},this, placeholders::_1, placeholders::_2);
    }

    template <typename T, typename U>
    void handle(T, U)
    {
    }
};

int main()
{
    return 0;
}

The callable passed to bind is an object of a concrete type handle_caller .传递给 bind 的可调用对象是具体类型handle_caller的 object。 It is not a template.它不是模板。 Only when cb is called the parameters are forwarded to handle_caller::operator() where the template arguments can be deduced.只有当调用cb时,参数才会被转发到handle_caller::operator() ,其中可以推导出模板 arguments。

Lambdas can do this out-of-the box, because a lambda with auto arguments is of a concrete type and only its operator() is a template: Lambdas 可以开箱即用,因为带有auto arguments 的 lambda 是具体类型,只有它的operator()是模板:

#include <iostream>
#include <functional>
#include <memory>

using namespace std;

struct foo {
    void f()
    {
        auto cb = std::bind([](auto f,auto t,auto u){ f->handle(t,u);},this, placeholders::_1, placeholders::_2);
    }

    template <typename T, typename U>
    void handle(T, U)
    {
    }
};

int main()
{
    return 0;
}

However, once you use the lambda there is no need for std::bind anymore, because you can bind the parameters via a lambda capture.但是,一旦您使用 lambda 就不再需要std::bind了,因为您可以通过 lambda 捕获来绑定参数。 std::bind is the ancient way to bind parameters, it is convoluted and has clunky syntax. std::bind是绑定参数的古老方法,它很复杂并且语法笨拙。 I have read of cases that can be done with std::bind but not with a lambda, but I have never encountered one.我读过可以用std::bind完成但不能用 lambda 完成的案例,但我从未遇到过。

PS: Note that I removed the shared_from_this stuff from your code, because I know it can be used wrong easily, but I am not sure how to use it correctly. PS:请注意,我从您的代码中删除了shared_from_this东西,因为我知道它很容易使用错误,但我不确定如何正确使用它。 As cb is only local to foo::f there is no need to worry about the lifetime of this in the example code.由于cb仅在foo::f本地,因此无需担心示例代码中this的生命周期。

&foo::handle is not valid C++, because foo::handle is not a function. foo::handle<int, int> is a function, and foo::handle<double, std::string> is a different function. &foo::handle无效 C++,因为foo::handle不是 function。foo::handle<int foo::handle<int, int>是 function,而foo::handle<double, std::string>是不同的 function。

You will have to wrap it in something , so you may as well use a lambda.你必须用一些东西把它包起来,所以你也可以使用 lambda。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM