我一直在查看gcc-4.7.2中std::function
和std::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);
}
答案 0 :(得分: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
。
答案 1 :(得分:1)
- 为什么_Tp和_Class :: *之间没有逗号?
jogojapan回答了这一部分
- 鉴于成员函数void foo :: bar()(在我下面的示例应用程序中),_Tp和_Class :: *将在何处解析?
Tp Class::*
之类的类型可以表示指向成员数据的指针或指向成员函数的指针,在后一种情况下Tp
将是函数类型。
在您的示例_Tp
中,函数类型为void ()
,_Class
将为foo