2

我一直在查看 gcc-4.7.2 的源代码,std::functionstd::bind遇到了一些我不理解的用于成员函数指针的语法。

我不明白的是_Maybe_wrap_member_pointer

template<typename _Tp, typename _Class>
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // note no comma here
  • _Tp为什么和之间没有逗号_Class::*

  • 给定成员函数void foo::bar()(在下面的示例应用程序中),这里将解决什么_Tp问题_Class::*

下面是我的示例应用程序,它绑定了成员函数指针和对象。(我已经提取了与std::bind成员函数的专业化/内部相关的源代码)

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

2 回答 2

7

这确实是用于将成员指针类型指定为模板参数的语法。

假设你有一堂课

struct Bar
{
  int n;
};

那么指向该成员的指针必须Bar::n将其类型声明为int Bar::*

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

请注意,int指的是指针指向的类型,并Bar::*表示“指向”成员的指针Bar

现在你的例子的功能,

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

接受一个模板参数(只有一个!),它表示一个类的成员指针类型,指向类型的_Class非静态数据成员_Tp

这是只有一个模板参数的类模板的模板特化:

template <typename T>
struct _Maybe_wrap_member_pointer
{ };

我们可以使用上面的简单类来实例化特化,如下所示:

_Maybe_wrap_member_pointer<int Bar::*>

或使用decltype

_Maybe_wrap_member_pointer<decltype(&Bar::n)>

在这两种情况下,_Tp都被推导为int,并且_Class被推导为Bar

于 2013-03-06T06:19:48.057 回答
1
  • 为什么 _Tp 和 _Class::* 之间没有逗号?

jogojapan 回答了这部分

  • 给定成员函数 void foo::bar() (在我下面的示例应用程序中), _Tp 和 _Class::* 将在这里解析什么?

诸如Tp Class::*可以表示指向成员数据的指针指向成员函数的指针的类型,在后一种情况下Tp将是函数类型。

在您的示例_Tp中将是函数类型void (),并且_Class将是foo

于 2013-03-06T10:13:25.807 回答