tôi có một cái foo
类,它有一个 bar
方法,它接受可调用的东西(函数指针/仿函数)。这个可调用的东西应该作为绑定(bind)元素传递给另一个方法 doit
和第三个方法 bar_cb
phương pháp.
#include
#include
class foo {
công cộng:
mẫu
void bar(T&& t) {
std::cout << "bar\n";
doit(std::bind(&foo::template bar_cb, this, std::forward(t)));
}
mẫu
void doit(T&& t) {
std::cout << "doit\n";
t();
}
mẫu
void bar_cb(T&& t) {
std::cout << "bar_cb\n";
t();
}
};
void lala() {
std::cout << "lala\n";
}
class functor {
công cộng:
void operator()() {
std::cout << "functor::operator()\n";
}
};
int chính() {
foo f;
functor fn;
f.bar(fn);
f.bar(std::bind(lala)); // error
trả về 0;
}
这对 functors
很好用,但对绑定(bind)函数作为 foo::bar
的参数(在我的例子中是 lala
)就不行了。是否可以将未知类型传递给方法并将其作为参数绑定(bind)到该方法中(如果可以,如何绑定(bind))?
我知道我可以在函数周围包装一个仿函数(例如 std::chức năng
)但是因为我可以调用一个不可知的类型我认为有一种方法也可以绑定(bind)它(我想我只是缺少一些简单的东西)。
Đây示例链接。
主要问题是您的 bar_cb(T&&)
不会推导模板参数,因为模板参数实际上是在使用 &foo::template bar_cb
时指定的带有一些模板参数 X
. bind()
然而,表达式将复制绑定(bind)函数,即它可能具有也可能不具有将被推导的类型。另外,std::bind()
Sẽ不会vượt qua bind()
-expression through but will rather call them!
最简单的解决方法是KHÔNGsử dụngstd::bind()
绑定(bind)函数而是使用 lambda 函数:
mẫu
void bar(T&& t) {
std::cout << "bar\n";
doit([=](){ this->bar_cb(t); });
}
这样做让编译器推断出 bar_cb()
的校正参数类型(对于 C++14,您可能希望使用捕获 [this,t = std::forward(t)]
,尽管您的 bar_cb()
仍然看不到右值)。
传递一个已经bind()
-通过另一个表达bind()
-表达式,没有 bind()
考虑内部bind()
-表达式 a bind()
-expression 你需要让它看起来好像不是 bind()
-表达。您可以使用薄函数包装器来实现:
template
class unbinder {
Fun fun;
công cộng:
template
unbinder(F&& fun): fun(std::forward(fun)) {}
template
auto operator()(Args&&... args) const
-> decltype(fun(std::forward(args)...)) {
return fun(std::forward(args)...);
}
};
template
auto unbind(Fun&& fun)
-> unbinder {
return unbinder(std::forward(fun));
}
由于函数存储在 bind()
中表达式将通过左值传递,您需要为 bar_cb()
进行不同的声明, 然而:
mẫu
void bar_cb(T& t) {
...
}
有了它,您可以注册 bind()
-表达式使用
f.bar(unbind(std::bind(lala)));
如果你想使用f.bar(std::bind(lala))
您需要 bar()
的条件定义: 如果它收到 bind()
-expression 它需要自动隐藏它是 bind()
的事实-通过应用表达 unbind()
或类似的东西:
mẫu
typename std::enable_if::type>::value>::type
bar(T&& t) {
std::cout << "bar (non-bind)\n";
doit(std::bind(&foo::template bar_cb, this, std::forward(t)));
}
mẫu
typename std::enable_if<>::type>::value>::type
bar(T&& t) {
std::cout << "bar (bind)\n";
doit(std::bind(&foo::template bar_cb<>>, this, unbind(std::forward(t))));
}
Tôi là một lập trình viên xuất sắc, rất giỏi!