diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index e3a7249..c481aa6 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -28,3 +28,23 @@ boostbook standalone_bind # How far down we go with TOC's generate.section.toc.level=0 ; + +xml mem_fn_ : mem_fn.qbk ; +boostbook standalone_mem_fn + : + mem_fn_ + : + boost.root=../../../.. + # File name of HTML output: + root.filename=mem_fn + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=0 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=0 + # How far down sections get TOC's + toc.section.depth=2 + # Max depth in each TOC: + toc.max.depth=2 + # How far down we go with TOC's + generate.section.toc.level=0 + ; diff --git a/doc/mem_fn.qbk b/doc/mem_fn.qbk new file mode 100644 index 0000000..9fe88d3 --- /dev/null +++ b/doc/mem_fn.qbk @@ -0,0 +1,32 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[library Boost.Member Function + [quickbook 1.6] + [id mem_fn] + [copyright 2001, 2002 Peter Dimov and Multi Media Ltd.] + [copyright 2003-2005 Peter Dimov] + [dirname bind] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +[include mem_fn/purpose.qbk] +[include mem_fn/faq.qbk] +[include mem_fn/interface.qbk] +[include mem_fn/implementation.qbk] +[include mem_fn/acknowledgements.qbk] diff --git a/doc/mem_fn/acknowledgements.qbk b/doc/mem_fn/acknowledgements.qbk new file mode 100644 index 0000000..e88514f --- /dev/null +++ b/doc/mem_fn/acknowledgements.qbk @@ -0,0 +1,26 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:acknowledgements Acknowledgements] + +* Rene Jager's initial suggestion of using traits classes to make `mem_fn` +adapt to user-defined smart pointers inspired the `get_pointer`-based design. + +* Numerous improvements were suggested during the formal review period by +Richard Crossley, Jens Maurer, Ed Brey, and others. Review manager was Darin +Adler. + +* Steve Anichini pointed out that COM interfaces use `__stdcall`. + +* Dave Abrahams modified `bind` and `mem_fn` to support `void` returns on +deficient compilers. + +* Daniel Boelzle pointed out that UDK uses `__cdecl`. + +[endsect] diff --git a/doc/mem_fn/faq.qbk b/doc/mem_fn/faq.qbk new file mode 100644 index 0000000..169c8f1 --- /dev/null +++ b/doc/mem_fn/faq.qbk @@ -0,0 +1,53 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:faq Frequently Asked Questions] + +[section Can `mem_fn` be used instead of the standard `std::mem_fun[_ref]` +adaptors?] + +Yes. For simple uses, `mem_fn` provides additional functionality that the +standard adaptors do not. Complicated expressions that use `std::bind1st`, +`std::bind2nd` or [@http://www.boost.org/doc/libs/1_31_0/libs/compose/index.htm Boost.Compose] +along with the standard adaptors can be rewritten using `boost::bind` that +automatically takes advantage of `mem_fn`. + +[endsect] + +[section Should I replace every occurence of `std::mem_fun[_ref]` with +`mem_fn` in my existing code?] + +No, unless you have good reasons to do so. `mem_fn` is not 100% compatible +with the standard adaptors, although it comes pretty close. In particular, +`mem_fn` does not return objects of type `std::[const_]mem_fun[1][_ref]_t`, as +the standard adaptors do, and it is not possible to fully describe the type of +the first argument using the standard `argument_type` and `first_argument_type` +nested typedefs. Libraries that need adaptable function objects in order to +function might not like `mem_fn`. + +[endsect] + +[section Does `mem_fn` work with COM methods?] + +Yes, if you [link mem_fn.implementation.stdcall `#define BOOST_MEM_FN_ENABLE_STDCALL]. + +[endsect] + +[section Why isn't `BOOST_MEM_FN_ENABLE_STDCALL` defined automatically?] + +Non-portable extensions, in general, should default to off to prevent vendor +lock-in. Had `BOOST_MEM_FN_ENABLE_STDCALL` been defined automatically, you +could have accidentally taken advantage of it without realizing that your code +is, perhaps, no longer portable. In addition, it is possible for the default +calling convention to be `__stdcall`, in which case enabling `__stdcall` +support will result in duplicate definitions. + +[endsect] + +[endsect] diff --git a/doc/mem_fn/implementation.qbk b/doc/mem_fn/implementation.qbk new file mode 100644 index 0000000..f7314ad --- /dev/null +++ b/doc/mem_fn/implementation.qbk @@ -0,0 +1,70 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:implementation Implementation] + +[section Files] + +* [@../../include/boost/mem_fn.hpp boost/mem_fn.hpp] (main header) +* [@../../include/boost/bind/mem_fn_cc.hpp boost/bind/mem_fn_cc.hpp] (used by `mem_fn.hpp`, do not include directly) +* [@../../include/boost/bind/mem_fn_vw.hpp boost/bind/mem_fn_vw.hpp] (used by `mem_fn.hpp`, do not include directly) +* [@../../include/boost/bind/mem_fn_template.hpp boost/bind/mem_fn_template.hpp] (used by `mem_fn.hpp`, do not include directly) +* [@../../test/mem_fn_test.cpp libs/bind/test/mem_fn_test.cpp] (test) +* [@../../test/mem_fn_derived_test.cpp libs/bind/test/mem_fn_derived_test.cpp] (test with derived objects) +* [@../../test/mem_fn_fastcall_test.cpp libs/bind/test/mem_fn_fastcall_test.cpp] (test for `__fastcall`) +* [@../../test/mem_fn_stdcall_test.cpp libs/bind/test/mem_fn_stdcall_test.cpp] (test for `__stdcall`) +* [@../../test/mem_fn_void_test.cpp libs/bind/test/mem_fn_void_test.cpp] (test for `void` returns) + +[endsect] + +[section Dependencies] + +* [@boost:/libs/config/config.htm Boost.Config] + +[endsect] + +[section Number of Arguments] + +This implementation supports member functions with up to eight arguments. This +is not an inherent limitation of the design, but an implementation detail. + +[endsect] + +[section:stdcall `__stdcall`, `__cdecl`, and `__fastcall` Support] + +Some platforms allow several types of member functions that differ by their +calling convention (the rules by which the function is invoked: how are +arguments passed, how is the return value handled, and who cleans up the stack + - if any.) + +For example, Windows API functions and COM interface member functions use a +calling convention known as `__stdcall`. Borland VCL components use +`__fastcall`. UDK, the component model of OpenOffice.org, uses `__cdecl`. + +To use `mem_fn` with `__stdcall` member functions, `#define` the macro +`BOOST_MEM_FN_ENABLE_STDCALL` before including ``. + +To use `mem_fn` with `__fastcall` member functions, `#define` the macro +`BOOST_MEM_FN_ENABLE_FASTCALL` before including ``. + +To use `mem_fn` with `__cdecl` member functions, `#define` the macro +`BOOST_MEM_FN_ENABLE_CDECL` before including ``. + +[*It is best to define these macros in the project options, via `-D` on the +command line, or as the first line in the translation unit (.cpp file) where +`mem_fn` is used.] Not following this rule can lead to obscure errors when a +header includes `mem_fn.hpp` before the macro has been defined. + +/[Note:/ this is a non-portable extension. It is not part of the interface./]/ + +/[Note:/ Some compilers provide only minimal support for the `__stdcall` keyword./]/ + +[endsect] + +[endsect] diff --git a/doc/mem_fn/interface.qbk b/doc/mem_fn/interface.qbk new file mode 100644 index 0000000..c0528a5 --- /dev/null +++ b/doc/mem_fn/interface.qbk @@ -0,0 +1,133 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:interface Interface] + +[section:synopsys Synopsis] + + namespace boost + { + template T * ``[link get_pointer_1 `get_pointer`]``(T * p); + + template ``/unspecified-1/`` ``[link mem_fn_1 `mem_fn`]``(R (T::*pmf) ()); + + template ``/unspecified-2/`` ``[link mem_fn_2 `mem_fn`]``(R (T::*pmf) () const); + + template ``/unspecified-2-1/`` ``[link mem_fn_2_1 `mem_fn`]``(R T::*pm); + + template ``/unspecified-3/`` ``[link mem_fn_3 `mem_fn`]``(R (T::*pmf) (A1)); + + template ``/unspecified-4/`` ``[link mem_fn_4 `mem_fn`]``(R (T::*pmf) (A1) const); + + template ``/unspecified-5/`` ``[link mem_fn_5 `mem_fn`]``(R (T::*pmf) (A1, A2)); + + template ``/unspecified-6/`` ``[link mem_fn_6 `mem_fn`]``(R (T::*pmf) (A1, A2) const); + + // implementation defined number of additional overloads for more arguments + } + +[endsect] + +[section Common requirements] + +All /unspecified-N/ types mentioned in the Synopsis are /CopyConstructible/ +and /Assignable/. Their copy constructors and assignment operators do not +throw exceptions. /unspecified-N/`::result_type` is defined as the return type +of the member function pointer passed as an argument to `mem_fn` (`R` in the +Synopsis.) /unspecified-2-1/`::result_type` is defined as `R`. + +[endsect] + +[section `get_pointer`] + +[#get_pointer_1] + + template T * get_pointer(T * p) + +* /Returns:/ `p`. + +* /Throws:/ Nothing. + +[endsect] + +[section `mem_fn`] + +[#mem_fn_1] + + template ``/unspecified-1/`` mem_fn(R (T::*pmf) ()) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is +equivalent to `(t.*pmf)()` when `t` is an l-value of type `T` or derived, +`(get_pointer(t)->*pmf)()` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_2] + + template ``/unspecified-2/`` mem_fn(R (T::*pmf) () const) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is +equivalent to `(t.*pmf)()` when `t` is of type `T` /[/`const`/]/ or derived, +`(get_pointer(t)->*pmf)()` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_2_1] + + template ``/unspecified-2-1/`` mem_fn(R T::*pm) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is +equivalent to `t.*pm` when `t` is of type `T` /[/`const`/]/ or derived, +`get_pointer(t)->*pm` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_3] + + template ``/unspecified-3/`` mem_fn(R (T::*pmf) (A1)) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1)` +is equivalent to `(t.*pmf)(a1)` when `t` is an l-value of type `T` or derived, +`(get_pointer(t)->*pmf)(a1)` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_4] + + template ``/unspecified-4/`` mem_fn(R (T::*pmf) (A1) const) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1)` +is equivalent to `(t.*pmf)(a1)` when `t` is of type `T` /[/`const`/]/ or derived, +`(get_pointer(t)->*pmf)(a1)` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_5] + + template ``/unspecified-5/`` mem_fn(R (T::*pmf) (A1, A2)) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1, a2)` +is equivalent to `(t.*pmf)(a1, a2)` when `t` is an l-value of type `T` or derived, +`(get_pointer(t)->*pmf)(a1, a2)` otherwise. + +* /Throws:/ Nothing. + +[#mem_fn_6] + + template ``/unspecified-6/`` mem_fn(R (T::*pmf) (A1, A2) const) + +* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1, a2)` +is equivalent to `(t.*pmf)(a1, a2)` when `t` is of type `T` /[/`const`/]/ or derived, +`(get_pointer(t)->*pmf)(a1, a2)` otherwise. + +* /Throws:/ Nothing. + +[endsect] + +[endsect] diff --git a/doc/mem_fn/purpose.qbk b/doc/mem_fn/purpose.qbk new file mode 100644 index 0000000..5fc6499 --- /dev/null +++ b/doc/mem_fn/purpose.qbk @@ -0,0 +1,93 @@ +[/ + / Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. + / Copyright (c) 2003-2005 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:purpose Purpose] + +`boost::mem_fn` is a generalization of the standard functions `std::mem_fun` +and `std::mem_fun_ref`. It supports member function pointers with more than +one argument, and the returned function object can take a pointer, a +reference, or a smart pointer to an object instance as its first argument. +`mem_fn` also supports pointers to data members by treating them as functions +taking no arguments and returning a (const) reference to the member. + +The purpose of `mem_fn` is twofold. First, it allows users to invoke a member +function on a container with the familiar + + std::for_each(v.begin(), v.end(), boost::mem_fn(&Shape::draw)); + +syntax, even when the container stores smart pointers. + +Second, it can be used as a building block by library developers that want to +treat a pointer to member function as a function object. A library might +define an enhanced `for_each` algorithm with an overload of the form: + + template void for_each(It first, It last, R (T::*pmf) ()) + { + std::for_each(first, last, boost::mem_fn(pmf)); + } + +that will allow the convenient syntax: + + for_each(v.begin(), v.end(), &Shape::draw); + +When documenting the feature, the library author will simply state: + + template void for_each(It first, It last, R (T::*pmf) ()); + +* /Effects:/ Equivalent to `std::for_each(first, last, boost::mem_fn(pmf))`. + +where `boost::mem_fn` can be a link to this page. See the +[@boost:/libs/bind/bind.html documentation of `bind`] for an example. + +`mem_fn` takes one argument, a pointer to a member, and returns a function +object suitable for use with standard or user-defined algorithms: + + struct X + { + void f(); + }; + + void g(std::vector & v) + { + std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); + }; + + void h(std::vector const & v) + { + std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); + }; + + void k(std::vector > const & v) + { + std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f)); + }; + +The returned function object takes the same arguments as the input member +function plus a "flexible" first argument that represents the object instance. + +When the function object is invoked with a first argument `x` that is neither +a pointer nor a reference to the appropriate class (`X` in the example above), +it uses `get_pointer(x)` to obtain a pointer from `x`. Library authors can +"register" their smart pointer classes by supplying an appropriate +`get_pointer` overload, allowing `mem_fn` to recognize and support them. + + +/[Note:/ `get_pointer` is not restricted to return a pointer. Any object that +can be used in a member function call expression `(x->*pmf)(...)` will work./]/ + +/[Note:/ the library uses an unqualified call to `get_pointer`. Therefore, it +will find, through argument-dependent lookup, `get_pointer` overloads that are +defined in the same namespace as the corresponding smart pointer class, in +addition to any `boost::get_pointer` overloads./]/ + +All function objects returned by `mem_fn` expose a `result_type` typedef that +represents the return type of the member function. For data members, +`result_type` is defined as the type of the member. + +[endsect]