2017-09-26 17 views
-1

그래, 이미이 예제가 작동 예제로 있지만 그냥 정리하려고합니다.함수 호출 내에서 바인드 사용

현재 콜백 루틴을 포함한 구독 스타일의 이벤트 시스템이 있습니다.

정규 함수와 클래스 멤버 함수를 저장소 변수에 추가해도 아무런 문제가 없습니다.

하지만 id는 내 Event.subscribe 메소드를 오버로드하여이를 정리하고 싶습니다.

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

지금 참으로 그것은 작동하지만, 엉터리 보인다. 문법은 무엇입니까? 그냥 미리 수행 할 수 있습니다.

몇 번 시도해 보았지만 제대로 이해할 수없는 것 같습니다.

은 그렇지 않은 것 :

template <class J> 
void subscribe(J::T cls,T& t); //Nope. 
void subscribe(J&& cls,T& t); //Nope. 

슈퍼 CLOSE : (들으 TOBI)

template< class J, class... Args > 
void subscribe(void(J::*funct)(Args), J& inst) { 
    using std::placeholders::_1; 
    subscribe(std::bind(funct, inst, _1)); 
} 

이제 단지 일반에 인수 목록이 필요합니다. 구문이 무엇인지

+1

확실하지,하지만 내가 생각 바인딩보다 람다를 선호합니다 – user463035818

+0

std :: thread ctor (3)에서 어떻게 구현되는지 확인할 수 있습니다 - http://en.cppreference.com/w/cpp/thread/thread/thread - 사소한 것이 아니므로 'std :: function'을 더 잘 사용하십시오 – Slava

+0

@Slava 그래서 어떻게 할 건가요? –

답변

0

그래서 난 그냥 미리 형성 할 수

messageCallback.subscribe(&B::callbk, b); 

사용자 인터페이스는 이미 모든 호출을 전달할 수 있습니다, 그것은 더 복잡하게 할 이유가 없다. EventObject은 콜백이 자유 함수인지 아니면 다른 것인지를 알지 못합니다. 나는 완전히 std::bind이 지루 좋은 보이지 않는 것을 동의하고 차라리 람다 사용합니다 :

EventObject<onMessageCallbackFunction> messageCallback; 
B b; 
messageCallback.subscribe([&b](const std::string& line){return b.callbk(line);}); 

PS를 : 나는 corretly tempalte를 사용하도록 의욕을 이해한다면 확실하지 않다. onMessageCallbackFunction과 함께 사용하기를 원하는 것 같습니다. 단순히 벡터를 저장하는 것이 좋을 것입니다.

PPS는 :

#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을 반환 멤버 함수만을위한 것입니다,하지만 난 심지어 귀찮게을 wouldnt : 완성도를 위해 여기 당신이 방법 내부 bind 숨길 수있는 방법입니다 일반화하고 람다를 사용하십시오.

+0

다른 이벤트 유형은 다른 인수를 갖는 함수에 콜백이 필요할 수 있습니다. –

+0

그래,이 방법이 효과적이지만 패턴을 검색 할 수있는 방법을 찾기 위해 벡터를 검색 할 수있는 능력이 없어지는 것 같습니다. "Un"-Subscribe 오브젝트를 원할 경우. 함수의 주소는 람다를 기반으로하기 때문에. –

+0

@StevenVenham 나는 호기심을 갖고 당신이 요구 한 것을 얻기 위해 노력했다. 그것은 나쁘게 보이지 않지만 실제로는 사용하지 않습니다. 람다에 의지합니다. – user463035818

1

나의 제안은 람다 (거의 모든면에서 우월하기 때문에 낡은 것이었지만 쓸모가 없어졌습니다)를 사용하는 것입니다.

람다를 따로 따로 철자하는 것은 결코 상처가 없습니다. 그렇게 할 때 성능 비용은 없습니다. 컴파일러는 불필요한 사본을 삭제합니다.

또한 std :: function을 사용하여 신호를 저장하고 호환되는 전달 함수 유형을 변환합니다.

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

에서 언급해야한다, 왜하고자하지 뭔가 같은 : 템플릿 \t 무효 SUB2 (무효 (J : * (SECURITY) 기능을 비활성화) (slot_type), J & INST) \t { \t} 직장? –

+0

J에 대한 포인터와 멤버 함수 포인터를 전달해야합니다. 그리고 그것은 매우 구체적 일 것입니다. –