1<?xml version="1.0" encoding="utf-8"?> 2<!-- 3 Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com> 4 5 Distributed under the Boost Software License, Version 1.0. 6 (See accompanying file LICENSE_1_0.txt or copy at 7 http://www.boost.org/LICENSE_1_0.txt) 8 --> 9<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" 10 "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> 11<section xmlns:xi="http://www.w3.org/2001/XInclude" id="function.tutorial" 12 last-revision="$Date$"> 13<title>Tutorial</title> 14 15<using-namespace name="boost"/> 16 17<para> Boost.Function has two syntactical forms: the preferred form 18and the portable form. The preferred form fits more closely with the 19C++ language and reduces the number of separate template parameters 20that need to be considered, often improving readability; however, the 21preferred form is not supported on all platforms due to compiler 22bugs. The compatible form will work on all compilers supported by 23Boost.Function. Consult the table below to determine which syntactic 24form to use for your compiler. 25 26 <informaltable> 27 <tgroup cols="2" align="left"> 28 <thead> 29 <row> 30 <entry>Preferred syntax</entry> 31 <entry>Portable syntax</entry> 32 </row> 33 </thead> 34 <tbody> 35 <row> 36 <entry> 37 <itemizedlist spacing="compact"> 38 <listitem><simpara>GNU C++ 2.95.x, 3.0.x and later versions</simpara></listitem> 39 <listitem><simpara>Comeau C++ 4.2.45.2</simpara></listitem> 40 <listitem><simpara>SGI MIPSpro 7.3.0</simpara></listitem> 41 <listitem><simpara>Intel C++ 5.0, 6.0</simpara></listitem> 42 <listitem><simpara>Compaq's cxx 6.2</simpara></listitem> 43 <listitem><simpara>Microsoft Visual C++ 7.1 and later versions</simpara></listitem> 44 </itemizedlist> 45 </entry> 46 <entry> 47 <itemizedlist spacing="compact"> 48 <listitem><simpara><emphasis>Any compiler supporting the preferred syntax</emphasis></simpara></listitem> 49 <listitem><simpara>Microsoft Visual C++ 6.0, 7.0</simpara></listitem> 50 <listitem><simpara>Borland C++ 5.5.1</simpara></listitem> 51 <listitem><simpara>Sun WorkShop 6 update 2 C++ 5.3</simpara></listitem> 52 <listitem><simpara>Metrowerks CodeWarrior 8.1</simpara></listitem> 53 </itemizedlist> 54 </entry> 55 </row> 56 </tbody> 57 </tgroup> 58 </informaltable> 59 60</para> 61 62<para> If your compiler does not appear in this list, please try the preferred syntax and report your results to the Boost list so that we can keep this table up-to-date.</para> 63 64<using-class name="boost::function"/> 65 66<section> 67<title>Basic Usage</title> <para> A function wrapper is defined simply 68by instantiating the <computeroutput>function</computeroutput> class 69template with the desired return type and argument types, formulated 70as a C++ function type. Any number of arguments may be supplied, up to 71some implementation-defined limit (10 is the default maximum). The 72following declares a function object wrapper 73<computeroutput>f</computeroutput> that takes two 74<computeroutput>int</computeroutput> parameters and returns a 75<computeroutput>float</computeroutput>: 76 77 <informaltable> 78 <tgroup cols="2" align="left"> 79 <thead> 80 <row> 81 <entry>Preferred syntax</entry> 82 <entry>Portable syntax</entry> 83 </row> 84 </thead> 85 <tbody> 86 <row> 87 <entry> 88<programlisting name="function.tutorial.arith.cxx98"><classname>boost::function</classname><float (int x, int y)> f;</programlisting> 89</entry> 90<entry> 91<programlisting name="function.tutorial.arith.portable"><classname alt="functionN">boost::function2</classname><float, int, int> f;</programlisting> 92</entry> 93 </row> 94 </tbody> 95 </tgroup> 96 </informaltable> 97</para> 98 99<para> By default, function object wrappers are empty, so we can create a 100function object to assign to <computeroutput>f</computeroutput>: 101 102<programlisting name="function.tutorial.int_div">struct int_div { 103 float operator()(int x, int y) const { return ((float)x)/y; }; 104};</programlisting> 105<programlisting name="function.tutorial.use_int_div">f = int_div();</programlisting> 106</para> 107 108<para> Now we can use <computeroutput>f</computeroutput> to execute 109the underlying function object 110<computeroutput>int_div</computeroutput>: 111 112<programlisting name="function.tutorial.call_int_div">std::cout << f(5, 3) << std::endl;</programlisting> 113</para> 114 115<para> We are free to assign any compatible function object to 116<computeroutput>f</computeroutput>. If 117<computeroutput>int_div</computeroutput> had been declared to take two 118<computeroutput>long</computeroutput> operands, the implicit 119conversions would have been applied to the arguments without any user 120interference. The only limit on the types of arguments is that they be 121CopyConstructible, so we can even use references and arrays: 122 123 <informaltable> 124 <tgroup cols="1" align="left"> 125 <thead><row><entry>Preferred syntax</entry></row></thead> 126 <tbody> 127 <row> 128 <entry> 129<programlisting name="function.tutorial.sum_avg_decl.cxx98"><classname>boost::function</classname><void (int values[], int n, int& sum, float& avg)> sum_avg;</programlisting> 130</entry> 131 </row> 132 </tbody> 133 </tgroup> 134 </informaltable> 135 <informaltable> 136 <tgroup cols="1" align="left"> 137 <thead><row><entry>Portable syntax</entry></row></thead> 138 <tbody> 139 <row> 140<entry> 141<programlisting name="function.tutorial.sum_avg_decl.portable"><classname alt="functionN">boost::function4</classname><void, int*, int, int&, float&> sum_avg;</programlisting> 142</entry> 143 </row> 144 </tbody> 145 </tgroup> 146 </informaltable> 147 148<programlisting name="function.tutorial.sum_avg">void do_sum_avg(int values[], int n, int& sum, float& avg) 149{ 150 sum = 0; 151 for (int i = 0; i < n; i++) 152 sum += values[i]; 153 avg = (float)sum / n; 154}</programlisting> 155 156 157<programlisting name="function.tutorial.use_sum_avg">sum_avg = &do_sum_avg;</programlisting> 158</para> 159 160<para> Invoking a function object wrapper that does not actually 161contain a function object is a precondition violation, much like 162trying to call through a null function pointer, and will throw a <classname>bad_function_call</classname> exception). We can check for an 163empty function object wrapper by using it in a boolean context (it evaluates <computeroutput>true</computeroutput> if the wrapper is not empty) or compare it against <computeroutput>0</computeroutput>. For instance: 164<programlisting name="function.tutorial.check_empty">if (f) 165 std::cout << f(5, 3) << std::endl; 166else 167 std::cout << "f has no target, so it is unsafe to call" << std::endl;</programlisting> 168</para> 169 170<para> Alternatively, 171<computeroutput><methodname>empty</methodname>()</computeroutput> 172method will return whether or not the wrapper is empty. </para> 173 174<para> Finally, we can clear out a function target by assigning it to <computeroutput>0</computeroutput> or by calling the <computeroutput><methodname>clear</methodname>()</computeroutput> member function, e.g., 175<programlisting name="function.tutorial.clear">f = 0;</programlisting> 176</para> 177 178</section> 179 180<section> 181 <title>Free functions</title> 182<para> Free function pointers can be considered singleton function objects with const function call operators, and can therefore be directly used with the function object wrappers: 183<programlisting name="function.tutorial.mul_ints">float mul_ints(int x, int y) { return ((float)x) * y; }</programlisting> 184<programlisting name="function.tutorial.use_mul_ints">f = &mul_ints;</programlisting> 185</para> 186 187<para> Note that the <computeroutput>&</computeroutput> isn't really necessary unless you happen to be using Microsoft Visual C++ version 6. </para> 188</section> 189 190<section> 191 <title>Member functions</title> 192 193<para> In many systems, callbacks often call to member functions of a 194particular object. This is often referred to as "argument binding", 195and is beyond the scope of Boost.Function. The use of member functions 196directly, however, is supported, so the following code is valid: 197 198<programlisting name="function.tutorial.X">struct X { 199 int foo(int); 200};</programlisting> 201 202 <informaltable> 203 <tgroup cols="2" align="left"> 204 <thead> 205 <row> 206 <entry>Preferred syntax</entry> 207 <entry>Portable syntax</entry> 208 </row> 209 </thead> 210 <tbody> 211 <row> 212 <entry> 213<programlisting name="function.tutorial.mem_fun.cxx98"><classname>boost::function</classname><int (X*, int)> f; 214 215f = &X::foo; 216 217X x; 218f(&x, 5);</programlisting> 219</entry> 220<entry> 221<programlisting name="function.tutorial.mem_fun.portable"><classname alt="functionN">boost::function2</classname><int, X*, int> f; 222 223f = &X::foo; 224 225X x; 226f(&x, 5);</programlisting> 227</entry> 228</row> 229</tbody> 230</tgroup> 231</informaltable> 232</para> 233 234<para> Several libraries exist that support argument binding. Three such libraries are summarized below: 235<itemizedlist> 236 <listitem> <para><libraryname>Bind</libraryname>. This library allows binding of 237 arguments for any function object. It is lightweight and very 238 portable.</para></listitem> 239 240 <listitem> <para>The C++ Standard library. Using 241 <computeroutput>std::bind1st</computeroutput> and 242 <computeroutput>std::mem_fun</computeroutput> together one can bind 243 the object of a pointer-to-member function for use with 244 Boost.Function: 245 246 <informaltable> 247 <tgroup cols="2" align="left"> 248 <thead> 249 <row> 250 <entry>Preferred syntax</entry> 251 <entry>Portable syntax</entry> 252 </row> 253 </thead> 254 <tbody> 255 <row> 256 <entry> 257<programlisting name="function.tutorial.std_bind.cxx98"> <classname>boost::function</classname><int (int)> f; 258X x; 259f = std::bind1st( 260 std::mem_fun(&X::foo), &x); 261f(5); // Call x.foo(5)</programlisting> 262</entry> 263<entry> 264<programlisting name="function.tutorial.std_bind.portable"> <classname alt="functionN">boost::function1</classname><int, int> f; 265X x; 266f = std::bind1st( 267 std::mem_fun(&X::foo), &x); 268f(5); // Call x.foo(5)</programlisting> 269</entry> 270 </row> 271 </tbody> 272 </tgroup> 273 </informaltable> 274</para> 275</listitem> 276 277 <listitem><para>The <libraryname>Lambda</libraryname> library. This library provides a powerful composition mechanism to construct function objects that uses very natural C++ syntax. Lambda requires a compiler that is reasonably conformant to the C++ standard. </para></listitem> 278</itemizedlist> 279</para> 280 281</section> 282 283<section> 284 <title>References to Function Objects</title> <para> In some cases it is 285 expensive (or semantically incorrect) to have Boost.Function clone a 286 function object. In such cases, it is possible to request that 287 Boost.Function keep only a reference to the actual function 288 object. This is done using the <computeroutput>ref</computeroutput> 289 and <computeroutput>cref</computeroutput> functions to wrap a 290 reference to a function object: 291 292 <informaltable> 293 <tgroup cols="2" align="left"> 294 <thead> 295 <row> 296 <entry>Preferred syntax</entry> 297 <entry>Portable syntax</entry> 298 </row> 299 </thead> 300 <tbody> 301 <row> 302 <entry> 303<programlisting name="function.tutorial.ref.cxx98">stateful_type a_function_object; 304<classname>boost::function</classname><int (int)> f; 305f = <functionname>boost::ref</functionname>(a_function_object); 306 307<classname>boost::function</classname><int (int)> f2(f);</programlisting> 308</entry> 309<entry> 310<programlisting name="function.tutorial.ref.portable">stateful_type a_function_object; 311<classname alt="functionN">boost::function1</classname><int, int> f; 312f = <functionname>boost::ref</functionname>(a_function_object); 313 314<classname alt="functionN">boost::function1</classname><int, int> f2(f);</programlisting> 315</entry> 316 </row> 317 </tbody> 318 </tgroup> 319 </informaltable> 320</para> 321 322<para> Here, <computeroutput>f</computeroutput> will not make a copy 323of <computeroutput>a_function_object</computeroutput>, nor will 324<computeroutput>f2</computeroutput> when it is targeted to 325<computeroutput>f</computeroutput>'s reference to 326<computeroutput>a_function_object</computeroutput>. Additionally, when 327using references to function objects, Boost.Function will not throw 328exceptions during assignment or construction. 329</para> 330</section> 331 332<section> 333 <title>Comparing Boost.Function function objects</title> 334 335 <para>Function object wrappers can be compared via <code>==</code> 336 or <code>!=</code> against any function object that can be stored 337 within the wrapper. If the function object wrapper contains a 338 function object of that type, it will be compared against the given 339 function object (which must be either be 340 <conceptname>EqualityComparable</conceptname> or have an overloaded <functionname>boost::function_equal</functionname>). For instance:</para> 341 342 <programlisting name="function.tutorial.compare">int compute_with_X(X*, int); 343 344f = &X::foo; 345assert(f == &X::foo); 346assert(&compute_with_X != f);</programlisting> 347 348 <para>When comparing against an instance of 349 <code><classname>reference_wrapper</classname></code>, the address 350 of the object in the 351 <code><classname>reference_wrapper</classname></code> is compared 352 against the address of the object stored by the function object 353 wrapper:</para> 354 355 <programlisting name="function.tutorial.compare-ref">a_stateful_object so1, so2; 356f = <functionname>boost::ref</functionname>(so1); 357assert(f == <functionname>boost::ref</functionname>(so1)); 358assert(f == so1); <emphasis>// Only if a_stateful_object is <conceptname>EqualityComparable</conceptname></emphasis> 359assert(f != <functionname>boost::ref</functionname>(so2));</programlisting> 360 361</section> 362 363</section> 364 365