簡體   English   中英

不使用std :: bind獲取成員函數的c ++ 11函數包裝器

[英]Get a c++11 function wrapper for a member function without using std::bind

我正在嘗試實現基本的信號/插槽系統。 一切都已啟動並運行,但是我正在嘗試提高實現的可用性。

目前,這是您連接信號的方式:

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的工作方式):

// prefered member function connect
// connect(instance_ptr, function_ptr)
mySignal.connect(&x, &X::memberFunction);

是否可以在不使用std :: bind的情況下獲取成員函數的std :: function對象? 如果沒有,是否有一種簡單的方法來生成std :: bind調用,僅使用成員函數的instance_ptr和function_ptr?

作為Signal的成員:

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,它們非常適合該任務。

這個技巧在C ++ 03中很好,但是對於C ++ 11,請使用Yakk的答案。

與此類似的東西可能會解決問題。

首先:制作一個僅綁定this的簡單版本的bind

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);}

最后,您想要的包裝器:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM