使用函数内部绑定调用
Using bind inside of function call
好吧,所以我已经有一个工作示例,但是我只是想清理它。
目前,我有一个带回调例程的订阅样式的事件系统。
我在为其添加常规功能和类成员功能时没有问题。
但我喜欢通过超载我的事件来清理它。
目前它可以做类似的事情:
template <class T>
class EventObject
{
public:
void subscribe(const T& arg)
{
this->events.push_back(arg);
}
std::vector<T> events;
}
然后在我的主要用途中使用:
void someCallback(const std::string& line)
{
cout <<line;
}
typedef std::function<void(const std::string& line)> onMessageCallbackFunction;
EventObject<onMessageCallbackFunction> messageCallback;
messageCallback.subscribe(someCallback);
现在,当我使用类成员功能时,泡菜会挺身而出。我讨厌在通过函数之前必须内在绑定该功能。它使代码看起来很脏。
例如:
class B
{
void callbk(const std::string& line) {}
};
B b;
using std::placeholders::_1;
onMessageCallbackFunction memfunc = std::bind(&B::callbk, b, _1);
messageCallback.subscribe(memfunc);
现在是可以的,但是看起来很糟糕。语法是什么,所以我可以预先形成:
messageCallback.subscribe(&B::callbk, b);
尝试了几个,但我似乎无法正确。
不是什么:
template <class J>
void subscribe(J::T cls,T& t); //Nope.
void subscribe(J&& cls,T& t); //Nope.
超关闭:( thx tobi)
template< class J, class... Args >
void subscribe(void(J::*funct)(Args), J& inst) {
using std::placeholders::_1;
subscribe(std::bind(funct, inst, _1));
}
现在只需要通用参数列表。
我的建议是使用lambda(std::bind
是过时的,因为Lambdas几乎在各个方面都优越)。
单独拼出Lambda永远不会受到伤害。这样做没有表现成本。编译器将出现不必要的副本。
我还将使用std ::函数存储您的信号并从兼容传递功能类型转换。
您的呼叫站点代码看起来像这样,我认为您会同意这是干净和表现力的:
EventObject<void(std::string)> messageCallback;
B b;
auto handler = [&b](std::string const& line)
{
b.callbk(line);
};
messageCallback.subscribe(handler);
完成示例:
#include <string>
#include <vector>
#include <functional>
#include <type_traits>
template<class Sig> struct EventObject;
template<class R, class...Args>
struct EventObject<R (Args...)>
{
using slot_type = std::function<R(Args...)>;
template
<
class F,
typename std::enable_if
<
std::is_constructible
<
slot_type,
typename std::decay<F>::type
>::value
>::type * = nullptr
>
void subscribe(F&& f)
{
subscribers_.emplace_back(std::forward<F>(f));
}
std::vector<slot_type> subscribers_;
};
class B
{
public:
void callbk(const std::string& line) {}
};
int main()
{
EventObject<void(std::string)> messageCallback;
B b;
auto handler = [&b](std::string const& line)
{
b.callbk(line);
};
messageCallback.subscribe(handler);
}
语法是什么,所以我可以预先形成:
messageCallback.subscribe(&B::callbk, b);
您的界面已经允许传递任何可召唤,并且没有理由使其更复杂。EventObject
不应知道回调是免费的功能还是其他功能。我完全同意std::bind
很乏味,看起来不好,我宁愿使用lambda:
EventObject<onMessageCallbackFunction> messageCallback;
B b;
messageCallback.subscribe([&b](const std::string& line){return b.callbk(line);});
ps:我不确定我是否会理解您使用tempalte的动机。似乎您只想与onMessageCallbackFunction
s一起使用它,因此仅存储其中的向量应该很好。
pps:为了完整的目的,您可以在方法中隐藏bind
:
#include <vector>
#include <string>
#include <iostream>
#include <functional>
using std::placeholders::_1;
template <class T>
class EventObject {
public:
void subscribe(const T& arg)
{
this->events.push_back(arg);
}
template<typename C>
void subscribe(void(C::*mem_fun)(const std::string&),C& c){
subscribe(std::bind(mem_fun,c,_1));
}
std::vector<T> events;
};
typedef std::function<void(const std::string& line)> onMessageCallbackFunction;
struct B {
void callbk(const std::string& line) {}
};
int main(){
EventObject<onMessageCallbackFunction> messageCallback;
B b;
messageCallback.subscribe(&B::callbk,b);
}
这仅适用于返回void
并返回string
的成员函数,但我什至不愿意使其成为通用并使用lambdas。
相关文章:
- 绑定派生类方法C++从实例范围之外的分隔 std::function 变量调用
- 努力将指向成员函数的指针绑定到类模板的T成员,然后在槽中调用
- 使用 Node.js 调用child_process与从 C 调用子进程并创建C++绑定以从 node.js 调用
- C++ 如何绑定和调用模板化类型方法
- std::tie 在从函数调用传递值时失败,并显示"无法绑定非常量左值引用"
- C++ 方法调用 (lvalue) 绑定到派生类中的函数 (rvalue),而不是基类中的函数 (lvalue)
- 仅在使用间接寻址时调用虚函数 — 经典的早期绑定问题?
- 当不处理指针时,请调用子类(虚拟)函数(较晚绑定)
- 使用函数内部绑定调用
- 为什么不允许将右值引用绑定到非常数引用,而允许在其中一个上调用非常数成员函数
- 使用boost数字绑定和对gesvd的lapack调用时出错
- 为什么在调用 glDrawArray 之前不需要绑定顶点缓冲区对象?
- 使用后期绑定从非私有上下文调用私有方法
- 缺少对指向成员函数的绑定指针的调用
- C++ Boost::bind:指向绑定函数的指针只能用于调用该函数
- 如何使用延迟绑定调用本机C库
- 观察c++中虚函数在汇编器中的后期绑定调用
- 如何从精神语义规则绑定/调用存储在fusion::vector中的boost::函数
- 对VB6接口方法的后期绑定调用
- C++ - std::绑定调用运算符()与完美的转发