I want to use std::bind with template function. Is it somehow possible?
P.S. 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.
#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;
}
CodePudding user response:
handle
is not a template function. There are no "template functions". handle
is a function template, ie it is a template, it is not a function. You cannot std::bind
to a template. You can only std::bind
to a callable.
The trick is to defer instantiation of the template and deduction of the template parameters to when the function is actually called:
#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
. 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.
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:
#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. std::bind
is the ancient way to bind parameters, it is convoluted and has clunky syntax. I have read of cases that can be done with std::bind
but not with a lambda, but I have never encountered one.
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. As cb
is only local to foo::f
there is no need to worry about the lifetime of this
in the example code.
CodePudding user response:
&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.
You will have to wrap it in something, so you may as well use a lambda.