将模板函数传递给 std::bind?
Pass template function to std::bind?
我想将 std::bind 与模板函数一起使用。有可能吗?
P.S。使用 std::bind
很重要,因为我通过 lambda 知道至少一种解决方案,想知道是否有 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;
}
&foo::handle
不是有效的 C++,因为 foo::handle
不是函数。 foo::handle<int, int>
是函数,foo::handle<double, std::string>
是不同的函数。
你必须用东西包装它,所以你也可以使用 lambda。
handle
不是模板函数。没有“模板功能”。 handle
是一个函数模板,即它是一个模板,它不是一个函数。您不能 std::bind
模板。您只能 std::bind
调用。
诀窍是将模板的实例化和模板参数的推导推迟到实际调用函数时:
#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;
}
传递给 bind 的可调用对象是一个具体类型的对象 handle_caller
。它不是模板。只有当 cb
被调用时,参数才会被转发到 handle_caller::operator()
,在那里可以推导出模板参数。
Lambda 可以执行此 out-of-the 框,因为带有 auto
个参数的 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;
}
但是,一旦您使用了 lambda,就不再需要 std::bind
,因为您可以通过 lambda 捕获来绑定参数。 std::bind
是绑定参数的古老方式,它很复杂并且语法笨拙。我读过可以用 std::bind
完成但不能用 lambda 完成的案例,但我从未遇到过。
PS:请注意,我从您的代码中删除了 shared_from_this
内容,因为我知道它很容易被错误使用,但我不确定如何正确使用它。由于 cb
仅对 foo::f
有效,因此无需担心示例代码中 this
的生命周期。
我想将 std::bind 与模板函数一起使用。有可能吗?
P.S。使用 std::bind
很重要,因为我通过 lambda 知道至少一种解决方案,想知道是否有 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;
}
&foo::handle
不是有效的 C++,因为 foo::handle
不是函数。 foo::handle<int, int>
是函数,foo::handle<double, std::string>
是不同的函数。
你必须用东西包装它,所以你也可以使用 lambda。
handle
不是模板函数。没有“模板功能”。 handle
是一个函数模板,即它是一个模板,它不是一个函数。您不能 std::bind
模板。您只能 std::bind
调用。
诀窍是将模板的实例化和模板参数的推导推迟到实际调用函数时:
#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;
}
传递给 bind 的可调用对象是一个具体类型的对象 handle_caller
。它不是模板。只有当 cb
被调用时,参数才会被转发到 handle_caller::operator()
,在那里可以推导出模板参数。
Lambda 可以执行此 out-of-the 框,因为带有 auto
个参数的 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;
}
但是,一旦您使用了 lambda,就不再需要 std::bind
,因为您可以通过 lambda 捕获来绑定参数。 std::bind
是绑定参数的古老方式,它很复杂并且语法笨拙。我读过可以用 std::bind
完成但不能用 lambda 完成的案例,但我从未遇到过。
PS:请注意,我从您的代码中删除了 shared_from_this
内容,因为我知道它很容易被错误使用,但我不确定如何正确使用它。由于 cb
仅对 foo::f
有效,因此无需担心示例代码中 this
的生命周期。