2013-03-06 6 views
2

std::functionstd::bind의 소스 코드를 gcc-4.7.2에서보고 있는데, 이해가되지 않는 멤버 함수 포인터에 사용되는 구문이 있습니다.이상한 템플릿 구문 <functional>

template<typename _Tp, typename _Class> 
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // note no comma here 
  • _Tp_Class::* 사이에 쉼표가 없습니다 :

    내가 이해하지 못하는 것은 _Maybe_wrap_member_pointer의 전문성은?

  • void foo::bar() (내 샘플 앱에서) _Tp_Class::*은 무엇을 여기에서 해결할 것입니까?

다음은 멤버 함수 포인터와 개체를 바인딩하는 샘플 응용 프로그램입니다. 이것은 참으로 템플릿 매개 변수로 멤버 포인터 타입을 지정하는 데 사용되는 구문입니다

#include <iostream> 
#include <functional> 

template<typename T> 
struct _Maybe_wrap_member_pointer; 

template<typename _Tp, typename _Class> 
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // <-- I don't understand this 
{            // why not <_Tp, _Class::*> 
    typedef std::_Mem_fn<_Tp _Class::*> type;  

    static type __do_wrap(_Tp _Class::* __pm) 
    { 
     return type(__pm); 
    } 
}; 

template<typename _Func, typename... _BoundArgs> 
struct _Bind_helper 
{ 
    typedef _Maybe_wrap_member_pointer<typename std::decay<_Func>::type> __maybe_type; 

    typedef typename __maybe_type::type __func_type; 
    typedef std::_Bind<__func_type(typename std::decay<_BoundArgs>::type...)> type; 
}; 

template<typename _Func, typename... _BoundArgs> 
inline 
typename _Bind_helper<_Func, _BoundArgs...>::type 
bind(_Func&& __f, _BoundArgs&&... __args) 
{ 
    typedef _Bind_helper<_Func, _BoundArgs...> __helper_type; 
    typedef typename __helper_type::__maybe_type __maybe_type; 
    typedef typename __helper_type::type   __result_type; 

    return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)), 
               std::forward<_BoundArgs>(__args)...); 
} 

struct foo 
{ 
    void bar() 
    { 
     std::cout << __func__ << std::endl; 
    } 
}; 

int main() 
{ 
    foo f; 

    std::function<void()> fun = bind(&foo::bar, f); 
    fun(); 

    exit(0); 
} 

답변

7

(I 멤버 함수에 대한 std::bind 전문/내부에 관련된 소스 코드를 뽑아있다). int 포인터 포인트 유형을 의미

int Bar::* p = &Bar::n; 

하는 것으로 :

int Bar::*로 그 유형을 선언해야 할 것이다 다음 클래스

struct Bar 
{ 
    int n; 
}; 

회원 Bar::n에 대한 포인터가 있다고 가정 to 및 Bar::*은 "Bar의 멤버에 대한 포인터"를 의미합니다. 이제

귀하의 예제의 기능

,

template<typename _Tp, typename _Class> 
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // note no comma here 

유형 _Tp의 비 정적 데이터 멤버를 가리키는 클래스 _Class의 멤버 포인터 유형을 나타내는 템플릿 인수 (하나!)를, 받아 들인다.

하나의 템플릿 매개 변수가있는 클래스 템플릿의 템플릿 특수화입니다 : 우리는이 같은 위의 간단한 클래스를 사용하여 전문화를 인스턴스화 할 수

template <typename T> 
struct _Maybe_wrap_member_pointer 
{ }; 

:

_Maybe_wrap_member_pointer<int Bar::*> 

또는 사용 decltype :

_Maybe_wrap_member_pointer<decltype(&Bar::n)> 

두 경우 모두 _Tpint으로 추론되며 _ClassBar으로 추론됩니다.

+1

은 그러므로 우리는 여전히()') (AN'연산자 데이터 멤버 유형은'_Tp' 클래스 될 수 있음을 추가 정의 할 수있을 것이다 (함수가 아닐지라도) 호출 가능해야한다. 'bind'와'function'은 그것을 돌 봅니다. –

+1

'_Tp'도 함수 타입이 될 수 있습니다.'Tp Class :: *'구조체는 멤버 데이터에 대한 포인터를 참조 할 수 있습니다. _or_ 멤버 함수 포인터 –

1
  • 왜 _Tp 및 _class :: 사이에 쉼표 *이 없다?

jogojapan 무엇을 _Tp하고 _class :: * 해결은 여기까지 (아래 내 샘플 응용 프로그램에서)이 부분

  • 을 감안할 때 멤버 함수 무효 foo는 : 바() 대답?

유형은 Tp Class::*로서의 기능 유형 될 Tp 후자의 경우에, 부재 데이터 또는 멤버 함수 포인터에 대한 포인터를 나타낼 수있다. 귀하의 예를 _Tp에서

는 함수 타입 void()되며 _Classfoo

+1

'void()'를 의미합니까? – Xeo

+0

+1 (질문에서 그 부분을 잊어 버렸습니다) – jogojapan

+0

죄송합니다, Xeo 님, 고쳐 주셨습니다. –