1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 3<html> 4<head> 5 <meta http-equiv="Content-Language" content="en-us"> 6 <meta http-equiv="Content-Type" content="text/html; charset=us-ascii"> 7 8 <title>Boost Function Object Adapter Library</title> 9</head> 10 11<body bgcolor="#FFFFFF" text="#000000"> 12 <table border="1" bgcolor="#007F7F" cellpadding="2" summary=""> 13 <tr> 14 <td bgcolor="#FFFFFF"><img src="../../boost.png" alt= 15 "boost.png (6897 bytes)" width="277" height="86"></td> 16 17 <td><a href="../../index.htm"><font face="Arial" color= 18 "#FFFFFF"><big>Home</big></font></a></td> 19 20 <td><a href="../libraries.htm"><font face="Arial" color= 21 "#FFFFFF"><big>Libraries</big></font></a></td> 22 23 <td><a href="http://www.boost.org/people/people.htm"><font face="Arial" color= 24 "#FFFFFF"><big>People</big></font></a></td> 25 26 <td><a href="http://www.boost.org/more/faq.htm"><font face="Arial" color= 27 "#FFFFFF"><big>FAQ</big></font></a></td> 28 29 <td><a href="../../more/index.htm"><font face="Arial" color= 30 "#FFFFFF"><big>More</big></font></a></td> 31 </tr> 32 </table> 33 34 <h1>Member Function Adapters</h1> 35 36 <p>The header <a href="../../boost/functional.hpp">functional.hpp</a> 37 includes improved versions of the full range of member function adapters 38 from the the C++ Standard Library (§20.3.8):</p> 39 40 <ul> 41 <li><tt>mem_fun_t</tt></li> 42 43 <li><tt>mem_fun1_t</tt></li> 44 45 <li><tt>const_mem_fun_t</tt></li> 46 47 <li><tt>const_mem_fun1_t</tt></li> 48 49 <li><tt>mem_fun_ref_t</tt></li> 50 51 <li><tt>mem_fun1_ref_t</tt></li> 52 53 <li><tt>const_mem_fun_ref_t</tt></li> 54 55 <li><tt>const_mem_fun1_ref_t</tt></li> 56 </ul> 57 58 <p>as well as the corresponding overloaded helper functions</p> 59 60 <ul> 61 <li><tt>mem_fun</tt></li> 62 63 <li><tt>mem_fun_ref</tt></li> 64 </ul> 65 66 <p>The following changes have been made to the adapters as specified in the 67 Standard:</p> 68 69 <ul> 70 <li>The <tt>first_argument_type</tt> typedef has been corrected for the 71 <tt>const_</tt> family of member function adapters (see <a href= 72 "#firstarg">below</a>).</li> 73 74 <li>The argument passed to <tt>mem_fun1_t</tt> and its variants is passed 75 using the <tt>call_traits::param_type</tt> for the member function's 76 argument type.</li> 77 </ul> 78 79 <h3 id="firstarg">first_argument_type</h3> 80 81 <p>The standard specifies <tt>const_mem_fun1_t</tt>, for example, like 82 this:</p> 83 84 <blockquote> 85 <pre> 86template <class S, class T, class A> class const_mem_fun1_t 87 : public binary_function<<strong>T*</strong>, A, S> { 88public: 89 explicit const_mem_fun1_t(S (T::*p)(A) const); 90 S operator()(<strong>const T*</strong> p, A x) const; 91}; 92</pre> 93 </blockquote> 94 95 <p>Note that the first argument to <tt>binary_function</tt> is <tt>T*</tt> 96 despite the fact that the first argument to <tt>operator()</tt> is actually 97 of type <tt><em>const</em> T*</tt>.</p> 98 99 <p>Does this matter? Well, consider what happens when we write</p> 100 101 <blockquote> 102 <pre> 103struct Foo { void bar(int) const; }; 104const Foo *cp = new Foo; 105std::bind1st(std::mem_fun(&Foo::bar), cp); 106</pre> 107 </blockquote> 108 109 <p>We have created a <tt>const_mem_fun1_t</tt> object which will 110 effectively contain the following</p> 111 112 <blockquote> 113 <pre> 114typedef Foo* first_argument_type; 115</pre> 116 </blockquote> 117 118 <p>The <tt>bind1st</tt> will then create a <tt>binder1st</tt> object that 119 will use this <tt>typedef</tt> as the type of a member which will be 120 initialised with <tt>cp</tt>. In other words, we will need to initialise a 121 <tt>Foo*</tt> member with a <tt>const Foo*</tt> pointer! Clearly this 122 is not possible, so to implement this your Standard Library vendor will 123 have had to cast away the constness of <tt>cp</tt>, probably within the 124 body of <tt>bind1st</tt>.</p> 125 126 <p>This hack will not suffice with the improved <a href= 127 "binders.html">binders</a> in this library, so we have had to provide 128 corrected versions of the member function adapters as well.</p> 129 130 <h3 id="args">Argument Types</h3> 131 132 <p>The standard defines <tt>mem_fun1_t</tt>, for example, like this 133 (§20.3.8 ¶2):</p> 134 135 <blockquote> 136 <pre> 137template <class S, class T, class A> class mem_fun1_t 138 : public binary_function<T*, A, S> { 139public: 140 explicit mem_fun1_t(S (T::*p)(<strong>A</strong>)); 141 S operator()(T* p, <strong>A</strong> x) const; 142}; 143</pre> 144 </blockquote> 145 146 <p>Note that the second argument to <tt>operator()</tt> is exactly the same 147 type as the argument to the member function. If this is a value type, the 148 argument will be passed by value and copied twice.</p> 149 150 <p>However, if we were to try and eliminate this inefficiency by instead 151 declaring the argument as <tt>const A&</tt>, then if A were a 152 reference type, we would have a reference to a reference, which is 153 currently illegal (but see <a href= 154 "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#106">C++ core 155 language issue number 106)</a></p> 156 157 <p>So the way in which we want to declare the second argument for 158 <tt>operator()</tt> depends on whether or not the member function's 159 argument is a reference. If it is a reference, we want to declare it simply 160 as <tt>A</tt>; if it is a value we want to declare it as 161 <tt>const A&</tt>.</p> 162 163 <p>The Boost <a href="../utility/call_traits.htm">call_traits</a> class 164 template contains a <tt>param_type</tt> typedef, which uses partial 165 specialisation to make precisely this decision. By declaring the 166 <tt>operator()</tt> as</p> 167 168 <blockquote> 169 <pre> 170S operator()(T* p, typename call_traits<A>::param_type x) const 171</pre> 172 </blockquote> 173 174 <p>we achieve the desired result - we improve efficiency without generating 175 references to references.</p> 176 177 <h3>Limitations</h3> 178 179 <p>The call traits template used to realise some improvements relies on 180 partial specialisation, so these improvements are only available on 181 compilers that support that feature. With other compilers, the argument 182 passed to the member function (in the <tt>mem_fun1_t</tt> family) will 183 always be passed by reference, thus generating the possibility of 184 references to references.</p> 185 <hr> 186 187 <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src= 188 "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional" 189 height="31" width="88"></a></p> 190 191 <p>Revised 192 <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->02 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38510" --></p> 193 194 <p><i>Copyright © 2000 Cadenza New Zealand Ltd.</i></p> 195 196 <p><i>Distributed under the Boost Software License, Version 1.0. (See 197 accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or 198 copy at <a href= 199 "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p> 200</body> 201</html> 202