Boost - Function: Douglas Gregor
Boost - Function: Douglas Gregor
Function
Douglas Gregor <dgregor
-at- cs.indiana.edu>
Copyright 2001-2004 Douglas Gregor Use, modification and distribution is subject to 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)
Table of Contents
Introduction .......................................................................................................................................................... 2 History & Compatibility Notes ................................................................................................................................. 3 Tutorial ................................................................................................................................................................ 4 Basic Usage .................................................................................................................................................. 4 Free functions ............................................................................................................................................... 5 Member functions .......................................................................................................................................... 5 References to Function Objects ......................................................................................................................... 6 Comparing Boost.Function function objects ........................................................................................................ 6 Reference ............................................................................................................................................................. 8 Denitions .................................................................................................................................................... 8 Header <boost/function.hpp> ........................................................................................................................... 9 Header <boost/function_equal.hpp> ................................................................................................................. 21 Frequently Asked Questions ................................................................................................................................... 23 Miscellaneous Notes ............................................................................................................................................. 25 Boost.Function vs. Function Pointers ............................................................................................................... 25 Performance ................................................................................................................................................ 25 Combatting virtual function "bloat" ................................................................................................................. 25 Acknowledgements ....................................................................................................................................... 26 Testsuite ............................................................................................................................................................. 27 Acceptance tests ........................................................................................................................................... 27 Negative tests .............................................................................................................................................. 29
Boost.Function
Introduction
The Boost.Function library contains a family of class templates that are function object wrappers. The notion is similar to a generalized callback. It shares features with function pointers in that both dene a call interface (e.g., a function taking two integer arguments and returning a oating-point value) through which some implementation can be called, and the implementation that is invoked may change throughout the course of the program. Generally, any place in which a function pointer would be used to defer a call or make a callback, Boost.Function can be used instead to allow the user greater exibility in the implementation of the target. Targets can be any 'compatible' function object (or function pointer), meaning that the arguments to the interface designated by Boost.Function can be converted to the arguments of the target function object.
Boost.Function
Boost.Function
Tutorial
Boost.Function has two syntactical forms: the preferred form and the portable form. The preferred form ts more closely with the C++ language and reduces the number of separate template parameters that need to be considered, often improving readability; however, the preferred form is not supported on all platforms due to compiler bugs. The compatible form will work on all compilers supported by Boost.Function. Consult the table below to determine which syntactic form to use for your compiler. Preferred syntax GNU C++ 2.95.x, 3.0.x and later versions Comeau C++ 4.2.45.2 SGI MIPSpro 7.3.0 Intel C++ 5.0, 6.0 Compaq's cxx 6.2 Microsoft Visual C++ 7.1 and later versions Portable syntax Any compiler supporting the preferred syntax Microsoft Visual C++ 6.0, 7.0 Borland C++ 5.5.1 Sun WorkShop 6 update 2 C++ 5.3 Metrowerks CodeWarrior 8.1
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.
Basic Usage
A function wrapper is dened simply by instantiating the function class template with the desired return type and argument types, formulated as a C++ function type. Any number of arguments may be supplied, up to some implementation-dened limit (10 is the default maximum). The following declares a function object wrapper f that takes two int parameters and returns a float: Preferred syntax
boost::function<float (int x, int y)> f;
Portable syntax
boost::function2<float, int, int> f;
By default, function object wrappers are empty, so we can create a function object to assign to f:
struct int_div { float operator()(int x, int y) const { return ((float)x)/y; }; };
f = int_div();
We are free to assign any compatible function object to f. If int_div had been declared to take two long operands, the implicit conversions would have been applied to the arguments without any user interference. The only limit on the types of arguments is that they be CopyConstructible, so we can even use references and arrays: Preferred syntax
boost::function<void (int values[], int n, int& sum, float& avg)> sum_avg;
Boost.Function
Portable syntax
boost::function4<void, int*, int, int&, float&> sum_avg;
void do_sum_avg(int values[], int n, int& sum, float& avg) { sum = 0; for (int i = 0; i < n; i++) sum += values[i]; avg = (float)sum / n; }
sum_avg = &do_sum_avg;
Invoking a function object wrapper that does not actually contain a function object is a precondition violation, much like trying to call through a null function pointer, and will throw a bad_function_call exception). We can check for an empty function object wrapper by using it in a boolean context (it evaluates true if the wrapper is not empty) or compare it against 0. For instance:
if (f) std::cout << f(5, 3) << std::endl; else std::cout << "f has no target, so it is unsafe to call" << std::endl;
Alternatively, empty() method will return whether or not the wrapper is empty. Finally, we can clear out a function target by assigning it to 0 or by calling the clear() member function, e.g.,
f = 0;
Free functions
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:
float mul_ints(int x, int y) { return ((float)x) * y; }
f = &mul_ints;
Note that the & isn't really necessary unless you happen to be using Microsoft Visual C++ version 6.
Member functions
In many systems, callbacks often call to member functions of a particular object. This is often referred to as "argument binding", and is beyond the scope of Boost.Function. The use of member functions directly, however, is supported, so the following code is valid:
struct X { int foo(int); };
Boost.Function
Preferred syntax
boost::function<int (X*, int)> f; f = &X::foo; X x; f(&x, 5);
Portable syntax
boost::function2<int, X*, int> f; f = &X::foo; X x; f(&x, 5);
Several libraries exist that support argument binding. Three such libraries are summarized below: Bind. This library allows binding of arguments for any function object. It is lightweight and very portable. The C++ Standard library. Using std::bind1st and std::mem_fun together one can bind the object of a pointer-to-member function for use with Boost.Function: Preferred syntax
boost::function<int (int)> f; X x; f = std::bind1st( std::mem_fun(&X::foo), &x); f(5); // Call x.foo(5)
Portable syntax
boost::function1<int, int> f; X x; f = std::bind1st( std::mem_fun(&X::foo), &x); f(5); // Call x.foo(5)
The Lambda 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.
Portable syntax
stateful_type a_function_object; boost::function1<int, int> f; f = boost::ref(a_function_object); boost::function1<int, int> f2(f);
Here, f will not make a copy of a_function_object, nor will f2 when it is targeted to f's reference to a_function_object. Additionally, when using references to function objects, Boost.Function will not throw exceptions during assignment or construction.
Boost.Function
When comparing against an instance of reference_wrapper, the address of the object in the reference_wrapper is compared against the address of the object stored by the function object wrapper:
a_stateful_object so1, so2; f = boost::ref(so1); assert(f == boost::ref(so1)); assert(f == so1); // Only if a_stateful_object is EqualityComparable assert(f != boost::ref(so2));
Boost.Function
Reference
Definitions
A function object f is compatible if for the given set of argument types Arg1, Arg2, ..., ArgN and a return type ResultType, the appropriate following function is well-formed:
// if ResultType is not void ResultType foo(Arg1 arg1, Arg2 arg2, ..., ArgN argN) { return f(arg1, arg2, ..., argN); } // if ResultType is void ResultType foo(Arg1 arg1, Arg2 arg2, ..., ArgN argN) { f(arg1, arg2, ..., argN); }
A special provision is made for pointers to member functions. Though they are not function objects, Boost.Function will adapt them internally to function objects. This requires that a pointer to member function of the form R (X::*mf)(Arg1, Arg2, ..., ArgN) cv-quals be adapted to a function object with the following function call operator overloads:
template<typename P> R operator()(cv-quals P& x, Arg1 arg1, Arg2 arg2, ..., ArgN argN) const { return (*x).*mf(arg1, arg2, ..., argN); }
A function object f of type F is stateless if it is a function pointer or if boost::is_stateless<F> is true. The construction of or copy to a Boost.Function object from a stateless function object will not cause exceptions to be thrown and will not allocate any storage.
Boost.Function
Header <boost/function.hpp>
namespace boost { class bad_function_call; class function_base; template<typename R, typename T1, typename T2, ..., typename TN> class functionN; template<typename T1, typename T2, ..., typename TN> void swap(functionN<T1, T2, ..., TN>&, functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>&, Functor); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(Functor, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>&, reference_wrapper<Functor>); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(reference_wrapper<Functor>, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator==(const functionN<T1, T2, ..., TN>&, const functionN<U1, U2, ..., UN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>&, Functor); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(Functor, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>&, reference_wrapper<Functor>); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(reference_wrapper<Functor>, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator!=(const functionN<T1, T2, ..., TN>&, const functionN<U1, U2, ..., UN>&); template<typename Signature> class function; template<typename Signature> void swap(function<Signature>&, function<Signature>&); template<typename Signature, typename Functor> bool operator==(const function<Signature>&, Functor); template<typename Signature, typename Functor> bool operator==(Functor, const function<Signature>&); template<typename Signature, typename Functor> bool operator==(const function<Signature>&, reference_wrapper<Functor>); template<typename Signature, typename Functor> bool operator==(reference_wrapper<Functor>, const function<Signature>&); template<typename Signature1, typename Signature2> void operator==(const function<Signature1>&, const function<Signature2>&); template<typename Signature, typename Functor> bool operator!=(const function<Signature>&, Functor); template<typename Signature, typename Functor> bool operator!=(Functor, const function<Signature>&); template<typename Signature, typename Functor> bool operator!=(const function<Signature>&, reference_wrapper<Functor>); template<typename Signature, typename Functor> bool operator!=(reference_wrapper<Functor>, const function<Signature>&); template<typename Signature1, typename Signature2> void operator!=(const function<Signature1>&, const function<Signature2>&); }
Boost.Function
Class bad_function_call
boost::bad_function_call An exception type thrown when an instance of a function object is empty when invoked.
Synopsis
// In header: <boost/function.hpp>
Description
bad_function_call public construct/copy/destruct
1.
bad_function_call();
Effects:
Class function_base
boost::function_base The common base class for all Boost.Function objects. Objects of type function_base may not be created directly.
Synopsis
// In header: <boost/function.hpp>
class function_base { public: // capacity bool empty() const; // target access template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const; template<typename Functor> bool contains(const Functor&) const; const std::type_info& target_type() const; };
Description
function_base capacity
1.
Returns: Throws:
10
Boost.Function
1.
template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const;
Returns: Throws: 2.
If this stores a target of type Functor, returns the address of the target. Otherwise, returns the NULL pointer. Will not throw.
Returns: 3.
Returns: Throws:
11
Boost.Function
Synopsis
// In header: <boost/function.hpp> template<typename R, typename T1, typename T2, class functionN : public function_base { public: // types typedef R result_type; typedef T1 argument_type; // If N == typedef T1 first_argument_type; // If N == typedef T2 second_argument_type; // If N == typedef T1 arg1_type; typedef T2 arg2_type; . . . typedef TN argN_type; // static constants static const int arity = N; // member classes/structs/unions // Lambda library support template<typename Args> struct sig { // types typedef result_type type; }; // construct/copy/destruct functionN(); functionN(const functionN&); template<typename F> functionN(F); template<typename F, typename Allocator> functionN(F, Allocator); functionN& operator=(const functionN&); ~functionN(); // modifiers void swap(const functionN&); void clear(); // capacity bool empty() const; operator safe_bool() const; bool operator!() const; // target access template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const; template<typename Functor> bool contains(const Functor&) const; const std::type_info& target_type() const; // invocation result_type operator()(arg1_type, arg2_type, ..., argN_type) const; }; // specialized algorithms template<typename T1, typename T2, ..., typename TN> void swap(functionN<T1, T2, ..., TN>&, functionN<T1, T2, ..., TN>&); ..., typename TN>
1 2 2
12
Boost.Function
// comparison operators template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>&, Functor); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(Functor, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>&, reference_wrapper<Functor>); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(reference_wrapper<Functor>, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator==(const functionN<T1, T2, ..., TN>&, const functionN<U1, U2, ..., UN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>&, Functor); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(Functor, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>&, reference_wrapper<Functor>); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(reference_wrapper<Functor>, const functionN<T1, T2, ..., TN>&); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator!=(const functionN<T1, T2, ..., TN>&, const functionN<U1, U2, ..., UN>&);
Description
Class template functionN is actually a family of related classes function0, function1, etc., up to some implementation-dened maximum. In this context, N refers to the number of parameters.
functionN public construct/copy/destruct
1.
functionN();
Postconditions: Throws: 2.
this->empty()
Postconditions: Throws: 3.
Contains a copy of the f's target, if it has one, or is empty if f.empty(). Will not throw unless copying the target of f throws.
Requires: Postconditions: 4.
F is a function object Callable from this. *this targets a copy of f if f is nonempty, or this->empty() if f is empty.
F is a function object Callable from this, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw. *this targets a copy of f if f is nonempty, or this->empty() if f is empty. If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.
13
Boost.Function
5.
Postconditions: 6.
If copy construction does not throw, *this targets a copy of f's target, if it has one, or is empty if f.empty(). If copy construction does throw, this->empty().
~functionN();
Effects:
functionN modifiers
1.
Effects: 2.
void clear();
Postconditions:
functionN capacity
this->empty()
1.
Returns: Throws: 2.
Returns: Throws: 3.
A safe_bool that evaluates false in a boolean context when this->empty(), and true otherwise. Will not throw.
Returns: Throws:
this->empty()
1.
template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const;
Returns: Throws: 2.
If this stores a target of type Functor, returns the address of the target. Otherwise, returns the NULL pointer. Will not throw.
Returns: 3.
Returns: Throws:
14
Boost.Function
functionN invocation
1.
f(a1, a2, ..., aN), where f is the target of *this. if R is void, nothing is returned; otherwise, the return value of the call to f is returned. bad_function_call if this->empty(). Otherwise, may through any exception thrown by the target function f.
Synopsis
// In header: <boost/function.hpp>
// Lambda library support template<typename Args> struct sig { // types typedef result_type type; }; functionN specialized algorithms
1.
template<typename T1, typename T2, ..., typename TN> void swap(functionN<T1, T2, ..., TN>& f1, functionN<T1, T2, ..., TN>& f2);
Effects:
f1.swap(f2)
1.
template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>& f, Functor g); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(Functor g, const functionN<T1, T2, ..., TN>& f); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(const functionN<T1, T2, ..., TN>& f, reference_wrapper<Functor> g); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator==(reference_wrapper<Functor> g, const functionN<T1, T2, ..., TN>& f); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator==(const functionN<T1, T2, ..., TN>& f1, const functionN<U1, U2, ..., UN>& f2);
Returns:
True when f stores an object of type Functor and one of the following conditions applies: g is of type reference_wrapper<Functor> and f.target<Functor>() == g.get_pointer(). g is not of type reference_wrapper<Functor> and function_equal(*(f.target<Functor>()), g). functionN objects are not EqualityComparable.
Notes:
15
Boost.Function
Rationale:
The safe_bool conversion opens a loophole whereby two functionN instances can be compared via ==, although this is not feasible to implement. The undened void operator== closes the loophole and ensures a compile-time or link-time error.
2.
template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>& f, Functor g); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(Functor g, const functionN<T1, T2, ..., TN>& f); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(const functionN<T1, T2, ..., TN>& f, reference_wrapper<Functor> g); template<typename T1, typename T2, ..., typename TN, typename Functor> bool operator!=(reference_wrapper<Functor> g, const functionN<T1, T2, ..., TN>& f); template<typename T1, typename T2, ..., typename TN, typename U1, typename U2, ..., typename UN> void operator!=(const functionN<T1, T2, ..., TN>& f1, const functionN<U1, U2, ..., UN>& f2);
Returns:
True when f does not store an object of type Functor or it stores an object of type Functor and one of the following conditions applies: g is of type reference_wrapper<Functor> and f.target<Functor>() != g.get_pointer(). g is not of type reference_wrapper<Functor> and !function_equal(*(f.target<Functor>()), g). functionN objects are not EqualityComparable. The safe_bool conversion opens a loophole whereby two functionN instances can be compared via !=, although this is not feasible to implement. The undened void operator!= closes the loophole and ensures a compile-time or link-time error.
Notes: Rationale:
16
Boost.Function
Synopsis
// In header: <boost/function.hpp> template<typename Signature> class function : public functionN<R, T1, T2, ..., TN> { public: // types typedef R result_type; typedef T1 argument_type; // If N == 1 typedef T1 first_argument_type; // If N == 2 typedef T2 second_argument_type; // If N == 2 typedef T1 arg1_type; typedef T2 arg2_type; . . . typedef TN argN_type; // static constants static const int arity = N; // member classes/structs/unions // Lambda library support template<typename Args> struct sig { // types typedef result_type type; }; // construct/copy/destruct function(); function(const functionN&); function(const function&); template<typename F> function(F); template<typename F, typename Allocator> function(F, Allocator); function& operator=(const function&); function& operator=(const function&); ~function(); // modifiers void swap(const function&); void clear(); // capacity bool empty() const; operator safe_bool() const; bool operator!() const; // target access template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const; template<typename Functor> bool contains(const Functor&) const; const std::type_info& target_type() const; // invocation result_type operator()(arg1_type, arg2_type, ..., argN_type) const; }; // specialized algorithms template<typename Signature>
17
Boost.Function
void swap(function<Signature>&, function<Signature>&); // comparison operators template<typename Signature, typename Functor> bool operator==(const function<Signature>&, Functor); template<typename Signature, typename Functor> bool operator==(Functor, const function<Signature>&); template<typename Signature, typename Functor> bool operator==(const function<Signature>&, reference_wrapper<Functor>); template<typename Signature, typename Functor> bool operator==(reference_wrapper<Functor>, const function<Signature>&); template<typename Signature1, typename Signature2> void operator==(const function<Signature1>&, const function<Signature2>&); template<typename Signature, typename Functor> bool operator!=(const function<Signature>&, Functor); template<typename Signature, typename Functor> bool operator!=(Functor, const function<Signature>&); template<typename Signature, typename Functor> bool operator!=(const function<Signature>&, reference_wrapper<Functor>); template<typename Signature, typename Functor> bool operator!=(reference_wrapper<Functor>, const function<Signature>&); template<typename Signature1, typename Signature2> void operator!=(const function<Signature1>&, const function<Signature2>&);
Description
Class template function is a thin wrapper around the numbered class templates function0, function1, etc. It accepts a function type with N arguments and will will derive from functionN instantiated with the arguments it receives. The semantics of all operations in class template function are equivalent to that of the underlying functionN object, although additional member functions are required to allow proper copy construction and copy assignment of function objects. Template Parameters 1.
typename Signature
1.
function();
Postconditions: Throws: 2.
this->empty()
Postconditions: Throws: 3.
Contains a copy of the f's target, if it has one, or is empty if f.empty(). Will not throw unless copying the target of f throws.
Postconditions: Throws: 4.
Contains a copy of the f's target, if it has one, or is empty if f.empty(). Will not throw unless copying the target of f throws.
Requires:
18
Boost.Function
Postconditions: 5.
F is a function object Callable from this, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw. *this targets a copy of f if f is nonempty, or this->empty() if f is empty. If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.
Postconditions: 7.
If copy construction does not throw, *this targets a copy of f's target, if it has one, or is empty if f.empty(). If copy construction does throw, this->empty().
Postconditions: Throws: 8.
If copy construction of the target of f does not throw, *this targets a copy of f's target, if it has one, or is empty if f.empty(). Will not throw when the target of f is a stateless function object or a reference to the function object. If copy construction does throw, this->empty().
~function();
Effects:
function modifiers
1.
Effects: 2.
void clear();
Postconditions: Throws:
function capacity
this->empty()
1.
Returns: Throws: 2.
Returns: Throws: 3.
A safe_bool that evaluates false in a boolean context when this->empty(), and true otherwise. Will not throw.
Returns: Throws:
this->empty()
19
Boost.Function
1.
template<typename Functor> Functor* target(); template<typename Functor> const Functor* target() const;
Returns: Throws: 2.
If this stores a target of type Functor, returns the address of the target. Otherwise, returns the NULL pointer. Will not throw.
Returns: 3.
Returns: Throws:
function invocation
1.
f(a1, a2, ..., aN), where f is the target of *this. if R is void, nothing is returned; otherwise, the return value of the call to f is returned. bad_function_call if this->empty(). Otherwise, may through any exception thrown by the target function f.
Synopsis
// In header: <boost/function.hpp>
// Lambda library support template<typename Args> struct sig { // types typedef result_type type; }; function specialized algorithms
1.
Effects:
f1.swap(f2)
20
Boost.Function
1.
template<typename Signature, typename Functor> bool operator==(const function<Signature>& f, Functor g); template<typename Signature, typename Functor> bool operator==(Functor g, const function<Signature>& f); template<typename Signature, typename Functor> bool operator==(const function<Signature>& f, reference_wrapper<Functor> g); template<typename Signature, typename Functor> bool operator==(reference_wrapper<Functor> g, const function<Signature>& f); template<typename Signature1, typename Signature2> void operator==(const function<Signature1>& f1, const function<Signature2>& f2);
Returns:
True when f stores an object of type Functor and one of the following conditions applies: g is of type reference_wrapper<Functor> and f.target<Functor>() == g.get_pointer(). g is not of type reference_wrapper<Functor> and function_equals(*(f.target<Functor>()), g). function objects are not EqualityComparable. The safe_bool conversion opens a loophole whereby two function instances can be compared via ==, although this is not feasible to implement. The undened void operator== closes the loophole and ensures a compiletime or link-time error.
Notes: Rationale:
2.
template<typename Signature, typename Functor> bool operator!=(const function<Signature>& f, Functor g); template<typename Signature, typename Functor> bool operator!=(Functor g, const function<Signature>& f); template<typename Signature, typename Functor> bool operator!=(const function<Signature>& f, reference_wrapper<Functor> g); template<typename Signature, typename Functor> bool operator!=(reference_wrapper<Functor> g, const function<Signature>& f); template<typename Signature1, typename Signature2> void operator!=(const function<Signature1>& f1, const function<Signature2>& f2);
Returns:
True when f does not store an object of type Functor or it stores an object of type Functor and one of the following conditions applies: g is of type reference_wrapper<Functor> and f.target<Functor>() != g.get_pointer(). g is not of type reference_wrapper<Functor> and !function_equals(*(f.target<Functor>()), g). function objects are not EqualityComparable. The safe_bool conversion opens a loophole whereby two function instances can be compared via !=, although this is not feasible to implement. The undened void operator!= closes the loophole and ensures a compiletime or link-time error.
Notes: Rationale:
Header <boost/function_equal.hpp>
namespace boost { template<typename F, typename G> bool function_equal(const F&, const G&); }
21
Boost.Function
Synopsis
// In header: <boost/function_equal.hpp>
Description
Returns: Throws:
f == g. Only if f == g throws.
22
Boost.Function
This is a valid usage of boost::function because void returns are not used. With void returns, we would attempting to compile ill-formed code similar to:
23
Boost.Function
In essence, not using void returns allows boost::function to swallow a return value. This is consistent with allowing the user to assign and invoke functions and function objects with parameters that don't exactly match. 4. Why (function) cloning? In November and December of 2000, the issue of cloning vs. reference counting was debated at length and it was decided that cloning gave more predictable semantics. I won't rehash the discussion here, but if it cloning is incorrect for a particular application a reference-counting allocator could be used. 5. How much overhead does a call through boost::function incur? The cost of boost::function can be reasonably consistently measured at around 20ns +/- 10 ns on a modern >2GHz platform versus directly inlining the code. However, the performance of your application may benet from or be disadvantaged by boost::function depending on how your C++ optimiser optimises. Similar to a standard function pointer, differences of order of 10% have been noted to the benet or disadvantage of using boost::function to call a function that contains a tight loop depending on your compilation circumstances. [Answer provided by Matt Hurd. See http://article.gmane.org/gmane.comp.lib.boost.devel/33278]
24
Boost.Function
Miscellaneous Notes
Boost.Function vs. Function Pointers
Boost.Function has several advantages over function pointers, namely: Boost.Function allows arbitrary compatible function objects to be targets (instead of requiring an exact function signature). Boost.Function may be used with argument-binding and other function object construction libraries. Boost.Function has predictible behavior when an empty function object is called. And, of course, function pointers have several advantages over Boost.Function: Function pointers are smaller (the size of one pointer instead of four or more) Function pointers are faster (Boost.Function may require two calls through function pointers) Function pointers are backward-compatible with C libraries. More readable error messages.
Performance
Function object wrapper size
Function object wrappers will be the size of a struct containing a member function pointer and two data pointers. The actual size can vary signicantly depending on the underlying platform; on 32-bit Mac OS X with GCC, this amounts to 16 bytes, while it is 32 bytes Windows with Visual C++. Additionally, the function object target may be allocated on the heap, if it cannot be placed into the small-object buffer in the boost::function object.
Copying efficiency
Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using ref) if the cost of this cloning becomes prohibitive. Small function objects can be stored within the boost::function object itself, improving copying efciency.
Invocation efficiency
With a properly inlining compiler, an invocation of a function object requires one call through a function pointer. If the call is to a free function pointer, an additional call must be made to that function pointer (unless the compiler has very powerful interprocedural analysis).
25
Boost.Function
Acknowledgements
Many people were involved in the construction of this library. William Kempf, Jesse Jones and Karl Nelson were all extremely helpful in isolating an interface and scope for the library. John Maddock managed the formal review, and many reviewers gave excellent comments on interface, implementation, and documentation. Peter Dimov led us to the function declarator-based syntax.
26
Boost.Function
Testsuite
Acceptance tests
27
Boost.Function
Test function_test.cpp
Type run
If failing... The boost::function class template may not be usable on your compiler. However, the library may still be usable via the boost::functionN class templates.
function_n_test.cpp
run
Test the capabilities of the boost::functionN class templates. Test the use of custom allocators. Allocators are ignored by the implementation. The exception-safety and performance guarantees given for stateless function objects may not be met by the implementation. Either Boost.Lambda does not work on the platform, or Boost.Function cannot safely be applied without the use of boost::unlambda.
allocator_test.cpp
run
stateless_test.cpp
run
lambda_test.cpp
run
contains_test.cpp
run
Test the operation of the target member function and the equality operators. Test the generation of a Boost.Function function object adaptor accepting 30 arguments. The Boost.Function library may work for function object adaptors of up to 10 parameters, but will be unable to generate adaptors for an arbitrary number of parameters. Failure often indicates an error in the compiler's preprocessor.
function_30.cpp
compile
Test the rst tutorial example. Test the rst tutorial example. Test the second tutorial example. Test the second tutorial example. Test member function example from tutorial. Test member function example from tutorial. Test standard binders example from tutorial. Test standard binders example from tutorial.
mem_fun_portable.cpp
run
std_bind_cxx98.cpp
run
std_bind_portable.cpp
run
28
Boost.Function
Test function_ref_cxx98.cpp
Type run
Description Test boost::ref example from tutorial. Test boost::ref example from tutorial.
If failing...
function_ref_portable.cpp
run
Negative tests
Test function_test_fail1.cpp Type compile-fail Description Test the (incorrect!) use of comparisons between Boost.Function function objects. Test the use of an incompatible function object with Boost.Function If failing... Intuitive (but incorrect!) code may compile and will give meaningless results.
function_test_fail2.cpp
compile-fail
29