首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不使用std::bind为成员函数获取c++11函数包装器

不使用std::bind为成员函数获取c++11函数包装器
EN

Stack Overflow用户
提问于 2014-07-14 21:24:52
回答 2查看 508关注 0票数 1

我正在尝试实现一个基本的信号/插槽系统。一切都已经启动和运行,但我正在努力提高我的实现的可用性。

目前,您是如何连接到一个信号的:

代码语言:javascript
复制
struct X
{
    void memberFunction(int a, int b)
    {
         // do something
    }
};

void globalStaticFunction(int a, int b)
{
    // do something
}

// this is what the signal::connect function looks like at the moment
ConnectionHandle connect(std::function<RetType(Args...)> func);


int main()
{
    // test instance
    X x;

    // example signal
    Signal<void(int, int)> mySignal;


    // connect a static function to the signal
    mySignal.connect(&globalStaticFunction);

    // connect a member function
    // here we have to use std::bind to get a std::function
    mySignal.connect(std::bind(&X::memberFunction, &x, _1, _2));
}

我想为用户提供一种更简单的绑定成员函数的方法。我有这样的想法(类似于Qt是如何做到的):

代码语言:javascript
复制
// prefered member function connect
// connect(instance_ptr, function_ptr)
mySignal.connect(&x, &X::memberFunction);

在不使用std::bind的情况下,可以为成员函数获取std::function对象吗?如果没有,是否有一种简单的方法来生成std::bind调用,只使用成员函数的instance_ptr和function_ptr?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-14 22:05:28

作为Signal的成员

代码语言:javascript
复制
template<typename C>
ConnectionHandle connect( C* c, RetType(C::*func)(Args...)) {
  return connect( [c,func](Args&&...args) {
    return (c->*func)( std::forward<Args>(args)... );
  });
}

template<typename C, typename Method, typename... Unused>
ConnectionHandle connect( C* c, Method* m, Unused&&...) {
  return connect( [c,func](Args&&...args) {
    return (c->*m)( std::forward<Args>(args)... );
  });
}

第一个重载使您能够区分重载的方法。

第二种方法,如果第一种失败,允许您使用与签名兼容的方法。

...部分确保第一个匹配更好,如果它们都匹配的话(我希望!)

Args&&...应该与std::function一起工作,前提是std::function是完全完美的转发。如果没有,请用Args...替换。

我认为没有必要使用bind或变体,因为我们将立即将其填充到std::function中。创建一个lambda,它们非常适合这项任务。

票数 7
EN

Stack Overflow用户

发布于 2014-07-14 21:31:21

这个技巧在C++03中很好,但是对于C++11,请使用Yakk的答案。

类似于此的东西很可能起作用了。

首先:创建一个简单的bind版本,它只绑定this

代码语言:javascript
复制
template<class T, class RetType, class...Args>
RetType CallMemFn(T* obj, RetType(T::*func)(Args...), Args...args)
{return ((*obj).*(func))(std::forward<Args>(args)...);}

template<class T, class RetType, class...Args>
struct boundthis {
    typedef RetType result_type;
    typedef T* thistype;
    typedef RetType(*signature)(Args...);
    boundthis(T* self, RetType(T::*func)(Args...)) :self(self), func(func) {}
    RetType operator()(Args...args) {return CallMemFn(self,func,std::forward<Args>(args)...);}
private:
    T* self;
    RetType(T::*func)(Args...);
};
template<class T, class RetType, class...Args>
boundthis<T,RetType,Args...> bindthis(T* self, RetType(T::*func)(Args...))
{return boundthis<T,RetType,Args...>(self, func);}

最后,你想要的包装:

代码语言:javascript
复制
template<class T, class RetType, class...Args>
ConnectionHandle connect(T* obj, RetType(T::*func)(Args...))
{return connect(std::function<RetType(Args...)>(bindthis(obj, func)));}

http://ideone.com/a2rze0

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24746234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档