gpt4 book ai didi

c++ - 绑定(bind)绑定(bind)函数作为参数

转载 作者:行者123 更新时间:2023-11-28 02:35:15 32 4
gpt4 key购买 nike

我有一个 foo 类,它有一个 bar 方法,它接受可调用的东西(函数指针/仿函数)。这个可调用的东西应该作为绑定(bind)元素传递给另一个方法 doit 和第三个方法 bar_cb 方法。

#include <functional>
#include <iostream>

class foo {
public:
template<typename T>
void bar(T&& t) {
std::cout << "bar\n";
doit(std::bind(&foo::template bar_cb<T>, this, std::forward<T>(t)));
}

template<typename T>
void doit(T&& t) {
std::cout << "doit\n";
t();
}

template<typename T>
void bar_cb(T&& t) {
std::cout << "bar_cb\n";
t();
}
};


void lala() {
std::cout << "lala\n";
}

class functor {
public:
void operator()() {
std::cout << "functor::operator()\n";
}
};


int main() {
foo f;
functor fn;
f.bar(fn);
f.bar(std::bind(lala)); // error

return 0;
}

这对 functors 很好用,但对绑定(bind)函数作为 foo::bar 的参数(在我的例子中是 lala)就不行了。是否可以将未知类型传递给方法并将其作为参数绑定(bind)到该方法中(如果可以,如何绑定(bind))?

我知道我可以在函数周围包装一个仿函数(例如 std::function)但是因为我可以调用一个不可知的类型我认为有一种方法也可以绑定(bind)它(我想我只是缺少一些简单的东西)。

Here示例链接。

最佳答案

主要问题是您的 bar_cb(T&&)不会推导模板参数,因为模板参数实际上是在使用 &foo::template bar_cb<X> 时指定的带有一些模板参数 X . bind()然而,表达式将复制绑定(bind)函数,即它可能具有也可能不具有将被推导的类型。另外,std::bind()不会通过 bind() -expression through but will rather call them!

最简单的解决方法是使用std::bind()绑定(bind)函数而是使用 lambda 函数:

template<typename T>
void bar(T&& t) {
std::cout << "bar\n";
doit([=](){ this->bar_cb(t); });
}

这样做让编译器推断出 bar_cb() 的校正参数类型(对于 C++14,您可能希望使用捕获 [this,t = std::forward<T>(t)],尽管您的 bar_cb() 仍然看不到右值)。

传递一个已经bind() -通过另一个表达bind() -表达式,没有 bind()考虑内部bind() -表达式 a bind() -expression 你需要让它看起来好像不是 bind() -表达。您可以使用薄函数包装器来实现:

template <typename Fun>
class unbinder {
Fun fun;
public:
template <typename F>
unbinder(F&& fun): fun(std::forward<F>(fun)) {}
template <typename... Args>
auto operator()(Args&&... args) const
-> decltype(fun(std::forward<Args>(args)...)) {
return fun(std::forward<Args>(args)...);
}
};
template <typename Fun>
auto unbind(Fun&& fun)
-> unbinder<Fun> {
return unbinder<Fun>(std::forward<Fun>(fun));
}

由于函数存储在 bind() 中表达式将通过左值传递,您需要为 bar_cb() 进行不同的声明, 然而:

template<typename T>
void bar_cb(T& t) {
...
}

有了它,您可以注册 bind() -表达式使用

f.bar(unbind(std::bind(lala)));

如果你想使用f.bar(std::bind(lala))您需要 bar() 的条件定义: 如果它收到 bind() -expression 它需要自动隐藏它是 bind() 的事实-通过应用表达 unbind()或类似的东西:

template<typename T>
typename std::enable_if<!std::is_bind_expression<typename std::decay<T>::type>::value>::type
bar(T&& t) {
std::cout << "bar (non-bind)\n";
doit(std::bind(&foo::template bar_cb<T>, this, std::forward<T>(t)));
}
template<typename T>
typename std::enable_if<std::is_bind_expression<typename std::decay<T>::type>::value>::type
bar(T&& t) {
std::cout << "bar (bind)\n";
doit(std::bind(&foo::template bar_cb<unbinder<T>>, this, unbind(std::forward<T>(t))));
}

关于c++ - 绑定(bind)绑定(bind)函数作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27698400/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com