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 id="function.faq" last-revision="$Date$"> 12 <title>Frequently Asked Questions</title> 13 14<qandaset> 15 <qandaentry> 16 <question><para>Why can't I compare 17 <classname>boost::function</classname> objects with 18 <code>operator==</code> or 19 <code>operator!=</code>?</para></question> 20 21 <answer> 22 <para>Comparison between <classname>boost::function</classname> 23 objects cannot be implemented "well", and therefore will not be 24 implemented. The typical semantics requested for <code>f == 25 g</code> given <classname>boost::function</classname> objects 26 <code>f</code> and <code>g</code> are:</para> 27 <itemizedlist> 28 <listitem><simpara>If <code>f</code> and <code>g</code> 29 store function objects of the same type, use that type's 30 <code>operator==</code> to compare 31 them.</simpara></listitem> 32 33 <listitem><simpara>If <code>f</code> and <code>g</code> 34 store function objects of different types, return 35 <code>false</code>.</simpara></listitem> 36 </itemizedlist> 37 <para>The problem occurs when the type of the function objects 38 stored by both <code>f</code> and <code>g</code> doesn't have an 39 <code>operator==</code>: we would like the expression <code>f == 40 g</code> to fail to compile, as occurs with, e.g., the standard 41 containers. However, this is not implementable for 42 <classname>boost::function</classname> because it necessarily 43 "erases" some type information after it has been assigned a 44 function object, so it cannot try to call 45 <code>operator==</code> later: it must either find a way to call 46 <code>operator==</code> now, or it will never be able to call it 47 later. Note, for instance, what happens if you try to put a 48 <code>float</code> value into a 49 <classname>boost::function</classname> object: you will get an 50 error at the assignment operator or constructor, not in 51 <code>operator()</code>, because the function-call expression 52 must be bound in the constructor or assignment operator.</para> 53 54 <para>The most promising approach is to find a method of 55 determining if <code>operator==</code> can be called for a 56 particular type, and then supporting it only when it is 57 available; in other situations, an exception would be 58 thrown. However, to date there is no known way to detect if an 59 arbitrary operator expression <code>f == g</code> is suitably 60 defined. The best solution known has the following undesirable 61 qualities:</para> 62 63 <orderedlist> 64 <listitem><simpara>Fails at compile-time for objects where 65 <code>operator==</code> is not accessible (e.g., because it is 66 <code>private</code>).</simpara></listitem> 67 68 <listitem><simpara>Fails at compile-time if calling 69 <code>operator==</code> is ambiguous.</simpara></listitem> 70 71 <listitem><simpara>Appears to be correct if the 72 <code>operator==</code> declaration is correct, even though 73 <code>operator==</code> may not compile.</simpara></listitem> 74 </orderedlist> 75 76 <para>All of these problems translate into failures in the 77 <classname>boost::function</classname> constructors or 78 assignment operator, <emphasis>even if the user never invokes 79 operator==</emphasis>. We can't do that to users.</para> 80 81 <para>The other option is to place the burden on users that want 82 to use <code>operator==</code>, e.g., by providing an 83 <code>is_equality_comparable</code> trait they may 84 specialize. This is a workable solution, but is dangerous in 85 practice, because forgetting to specialize the trait will result 86 in unexpected exceptions being thrown from 87 <classname>boost::function</classname>'s 88 <code>operator==</code>. This essentially negates the usefulness 89 of <code>operator==</code> in the context in which it is most 90 desired: multitarget callbacks. The 91 <libraryname>Signals</libraryname> library has a way around 92 this.</para> 93 </answer> 94 </qandaentry> 95 96 <qandaentry> 97 <question><para>I see void pointers; is this [mess] type safe?</para></question> 98 <answer> 99<para>Yes, <computeroutput>boost::function</computeroutput> is type 100safe even though it uses void pointers and pointers to functions 101returning void and taking no arguments. Essentially, all type 102information is encoded in the functions that manage and invoke 103function pointers and function objects. Only these functions are 104instantiated with the exact type that is pointed to by the void 105pointer or pointer to void function. The reason that both are required 106is that one may cast between void pointers and object pointers safely 107or between different types of function pointers (provided you don't 108invoke a function pointer with the wrong type). </para> 109 </answer> 110 </qandaentry> 111 112 <qandaentry> 113 <question><para>Why are there workarounds for void returns? C++ allows them!</para></question> 114 <answer><para>Void returns are permitted by the C++ standard, as in this code snippet: 115<programlisting>void f(); 116void g() { return f(); }</programlisting> 117 </para> 118 119 <para> This is a valid usage of <computeroutput>boost::function</computeroutput> because void returns are not used. With void returns, we would attempting to compile ill-formed code similar to: 120<programlisting>int f(); 121void g() { return f(); }</programlisting> 122</para> 123 124<para> In essence, not using void returns allows 125<computeroutput>boost::function</computeroutput> to swallow a return value. This is 126consistent with allowing the user to assign and invoke functions and 127function objects with parameters that don't exactly match.</para> 128 129 </answer> 130 </qandaentry> 131 132 <qandaentry> 133 <question><para>Why (function) cloning?</para></question> 134 <answer> 135 <para>In November and December of 2000, the issue of cloning 136 vs. reference counting was debated at length and it was decided 137 that cloning gave more predictable semantics. I won't rehash the 138 discussion here, but if it cloning is incorrect for a particular 139 application a reference-counting allocator could be used.</para> 140 </answer> 141 </qandaentry> 142 143 <qandaentry> 144 <question><para>How much overhead does a call through <code><classname>boost::function</classname></code> incur?</para></question> 145 <answer> 146 <para>The cost of <code>boost::function</code> can be reasonably 147 consistently measured at around 20ns +/- 10 ns on a modern >2GHz 148 platform versus directly inlining the code.</para> 149 150 <para>However, the performance of your application may benefit 151 from or be disadvantaged by <code>boost::function</code> 152 depending on how your C++ optimiser optimises. Similar to a 153 standard function pointer, differences of order of 10% have been 154 noted to the benefit or disadvantage of using 155 <code>boost::function</code> to call a function that contains a 156 tight loop depending on your compilation circumstances.</para> 157 158 <para>[Answer provided by Matt Hurd. See <ulink url="http://article.gmane.org/gmane.comp.lib.boost.devel/33278"/>]</para> 159 </answer> 160 </qandaentry> 161</qandaset> 162 163</section> 164