版权所有 © 2001, 2002 Peter Dimov 和 Multi Media Ltd.
版权所有 © 2003-2005 Peter Dimov
根据 Boost 软件许可,版本 1.0 分发。
目录
boost::mem_fn
是标准函数 std::mem_fun
和 std::mem_fun_ref
的泛化。它支持具有多个参数的成员函数指针,并且返回的函数对象可以将指向对象实例的指针、引用或智能指针作为其第一个参数。mem_fn
还支持指向数据成员的指针,方法是将它们视为不带参数并返回对成员的(const)引用的函数。
mem_fn
的目的是双重的。首先,它允许用户在容器上调用成员函数,即使容器存储了智能指针,也可以使用熟悉的
std::for_each(v.begin(), v.end(), boost::mem_fn(&Shape::draw));
语法。
其次,库开发人员可以使用它作为构建块,他们希望将成员函数指针视为函数对象。库可能会定义一个增强的 for_each
算法,其重载形式为
template<class It, class R, class T> void for_each(It first, It last, R (T::*pmf) ()) { std::for_each(first, last, boost::mem_fn(pmf)); }
这将允许方便的语法
for_each(v.begin(), v.end(), &Shape::draw);
在记录该功能时,库作者只需声明
template<class It, class R, class T> void for_each(It first, It last, R (T::*pmf) ());
std::for_each(first, last, boost::mem_fn(pmf))
。其中 boost::mem_fn
可以是指向此页面的链接。有关示例,请参阅 bind
的文档。
mem_fn
接受一个参数,即指向成员的指针,并返回一个适用于标准或用户定义算法的函数对象
struct X { void f(); }; void g(std::vector<X> & v) { std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); }; void h(std::vector<X *> const & v) { std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); }; void k(std::vector<boost::shared_ptr<X> > const & v) { std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); };
返回的函数对象接受与输入成员函数相同的参数,外加一个“灵活”的第一个参数,该参数表示对象实例。
当使用既不是指针也不是对适当类(上面示例中的 X
)的引用的第一个参数 x
调用函数对象时,它使用 get_pointer(x)
从 x
获取指针。库作者可以通过提供适当的 get_pointer
重载来“注册”他们的智能指针类,从而允许 mem_fn
识别和支持它们。
[注意: get_pointer
不限于返回指针。任何可以在成员函数调用表达式 (x->*pmf)(...)
中使用的对象都可以工作。]
[注意: 该库使用对 get_pointer
的非限定调用。因此,它将通过参数依赖查找找到与相应的智能指针类在同一命名空间中定义的 get_pointer
重载,以及任何 boost::get_pointer
重载。]
由 mem_fn
返回的所有函数对象都公开一个 result_type
typedef,它表示成员函数的返回类型。对于数据成员,result_type
定义为成员的类型。
是的。对于简单的用途,mem_fn
提供了标准适配器不具备的附加功能。使用 std::bind1st
、std::bind2nd
或 Boost.Compose 以及标准适配器的复杂表达式可以使用自动利用 mem_fn
的 boost::bind
重写。
不,除非您有充分的理由这样做。mem_fn
与标准适配器并非 100% 兼容,尽管它非常接近。特别是,mem_fn
不返回 std::[const_]mem_fun[1][_ref]_t
类型的对象,因为标准适配器会这样做,并且不可能使用标准 argument_type
和 first_argument_type
嵌套 typedef 完全描述第一个参数的类型。需要可适应函数对象才能正常运行的库可能不喜欢 mem_fn
。
通常,非可移植扩展应默认为关闭,以防止供应商锁定。如果 BOOST_MEM_FN_ENABLE_STDCALL
已自动定义,则您可能在没有意识到您的代码可能不再可移植的情况下意外地利用了它。此外,默认调用约定可能是 __stdcall
,在这种情况下,启用 __stdcall
支持将导致重复定义。
namespace boost { template<class T> T *get_pointer
(T * p); template<class R, class T> unspecified-1mem_fn
(R (T::*pmf) ()); template<class R, class T> unspecified-2mem_fn
(R (T::*pmf) () const); template<class R, class T> unspecified-2-1mem_fn
(R T::*pm); template<class R, class T, class A1> unspecified-3mem_fn
(R (T::*pmf) (A1)); template<class R, class T, class A1> unspecified-4mem_fn
(R (T::*pmf) (A1) const); template<class R, class T, class A1, class A2> unspecified-5mem_fn
(R (T::*pmf) (A1, A2)); template<class R, class T, class A1, class A2> unspecified-6mem_fn
(R (T::*pmf) (A1, A2) const); // implementation defined number of additional overloads for more arguments }
概要中提到的所有 unspecified-N 类型都是 CopyConstructible 和 Assignable。它们的复制构造函数和赋值运算符不会引发异常。unspecified-N::result_type
定义为作为参数传递给 mem_fn
的成员函数指针的返回类型(概要中的 R
)。unspecified-2-1::result_type
定义为 R
。
template<class R, class T> unspecified-1 mem_fn(R (T::*pmf) ())
t
是类型 T
或派生的左值时,表达式 ϝ(t)
等效于 (t.*pmf)()
;否则等效于 (get_pointer(t)->*pmf)()
。template<class R, class T> unspecified-2 mem_fn(R (T::*pmf) () const)
t
是类型 T
[const
] 或派生类型时,表达式 ϝ(t)
等效于 (t.*pmf)()
;否则等效于 (get_pointer(t)->*pmf)()
。template<class R, class T> unspecified-2-1 mem_fn(R T::*pm)
t
是类型 T
[const
] 或派生类型时,表达式 ϝ(t)
等效于 t.*pm
;否则等效于 get_pointer(t)->*pm
。template<class R, class T, class A1> unspecified-3 mem_fn(R (T::*pmf) (A1))
t
是类型 T
或派生的左值时,表达式 ϝ(t, a1)
等效于 (t.*pmf)(a1)
;否则等效于 (get_pointer(t)->*pmf)(a1)
。template<class R, class T, class A1> unspecified-4 mem_fn(R (T::*pmf) (A1) const)
t
是类型 T
[const
] 或派生类型时,表达式 ϝ(t, a1)
等效于 (t.*pmf)(a1)
;否则等效于 (get_pointer(t)->*pmf)(a1)
。template<class R, class T, class A1, class A2> unspecified-5 mem_fn(R (T::*pmf) (A1, A2))
t
是类型 T
或派生的左值时,表达式 ϝ(t, a1, a2)
等效于 (t.*pmf)(a1, a2)
;否则等效于 (get_pointer(t)->*pmf)(a1, a2)
。template<class R, class T, class A1, class A2> unspecified-6 mem_fn(R (T::*pmf) (A1, A2) const)
t
是类型 T
[const
] 或派生类型时,表达式 ϝ(t, a1, a2)
等效于 (t.*pmf)(a1, a2)
;否则等效于 (get_pointer(t)->*pmf)(a1, a2)
。mem_fn.hpp
使用,请勿直接包含)mem_fn.hpp
使用,请勿直接包含)mem_fn.hpp
使用,请勿直接包含)__fastcall
的测试)__stdcall
的测试)void
返回值的测试)此实现最多支持具有八个参数的成员函数。这不是设计的固有限制,而是实现细节。
某些平台允许几种类型的成员函数,这些函数因其调用约定(调用函数的规则:如何传递参数,如何处理返回值以及谁清理堆栈 - 如果有)而异。
例如,Windows API 函数和 COM 接口成员函数使用称为 __stdcall
的调用约定。Borland VCL 组件使用 __fastcall
。UDK,OpenOffice.org 的组件模型,使用 __cdecl
。
要将 mem_fn
与 __stdcall
成员函数一起使用,请在包含 <boost/mem_fn.hpp>
之前 #define
宏 BOOST_MEM_FN_ENABLE_STDCALL
。
要将 mem_fn
与 __fastcall
成员函数一起使用,请在包含 <boost/mem_fn.hpp>
之前 #define
宏 BOOST_MEM_FN_ENABLE_FASTCALL
。
要将 mem_fn
与 __cdecl
成员函数一起使用,请在包含 <boost/mem_fn.hpp>
之前 #define
宏 BOOST_MEM_FN_ENABLE_CDECL
。
最好在项目选项中定义这些宏,通过命令行上的 -D
,或作为使用 mem_fn
的转换单元 (.cpp 文件) 中的第一行。 不遵循此规则可能会在头文件在宏定义之前包含 mem_fn.hpp
时导致模糊的错误。
[注意: 这是一个非可移植的扩展。它不是接口的一部分。]
[注意: 某些编译器仅提供对 __stdcall
关键字的最低限度支持。]
mem_fn
适应用户定义的智能指针的建议启发了基于 get_pointer
的设计。__stdcall
。bind
和 mem_fn
以支持缺陷编译器上的 void
返回值。__cdecl
。Agustín Bergé 将此文档移植到 Quickbook。