Compare commits

..

1 Commits

Author SHA1 Message Date
922ce7b8ae Branch at revision 46530
[SVN r46531]
2008-06-19 18:57:10 +00:00
21 changed files with 438 additions and 1319 deletions

View File

@ -3,14 +3,8 @@
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at # (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
project function/doc ; project boost/doc ;
import boostbook : boostbook ; import boostbook : boostbook ;
boostbook function-doc boostbook function-doc : function.xml ;
:
function.xml
:
<xsl:param>boost.root=../../../..
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;

View File

@ -13,35 +13,6 @@
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para><bold>Version 1.52.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Move constructors and move assignment
operators added (only for compilers with C++11 rvalue
references support). Original patch
contributed by Antony Polukhin.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.37.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Improved the performance of Boost.Function's
swap() operation for large function objects. Original patch
contributed by Niels Dekker.</para></listitem>
<listitem><para>Added a new header &lt;boost/function/function_typeof.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
<listitem><para>Added a new header &lt;boost/function/function_fwd.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
<listitem><para>The <methodname alt="boost::function::target">target</methodname>()
function now respects the cv-qualifiers of function objects
stored by reference
(using <classname>boost::reference_wrapper</classname>), such
that a reference to a <code>const</code> function object cannot
be accessed as a reference to a non-<code>const</code> function
object.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.36.0</bold>: </para> <listitem><para><bold>Version 1.36.0</bold>: </para>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para>Boost.Function now implements allocator support <listitem><para>Boost.Function now implements allocator support

View File

@ -58,7 +58,7 @@
<para>A function object <code>f</code> of <para>A function object <code>f</code> of
type <code>F</code> is type <code>F</code> is
<emphasis>stateless</emphasis> if it is a function pointer or if <emphasis>stateless</emphasis> if it is a function pointer or if
<code><classname>boost::is_stateless</classname>&lt;F&gt;</code> <code><classname>boost::is_stateless</classname>&lt;T&gt;</code>
is true. The construction of or copy to a Boost.Function object is true. The construction of or copy to a Boost.Function object
from a stateless function object will not cause exceptions to be from a stateless function object will not cause exceptions to be
thrown and will not allocate any storage. thrown and will not allocate any storage.
@ -128,7 +128,7 @@
<method name="target_type" cv="const"> <method name="target_type" cv="const">
<type>const std::type_info&amp;</type> <type>const std::type_info&amp;</type>
<returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>. Works even with RTTI off.</simpara></returns> <returns><simpara><code>typeid</code> of the target function object, or <code>typeid(void)</code> if <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws> <throws><simpara>Will not throw.</simpara></throws>
</method> </method>
</method-group> </method-group>
@ -203,15 +203,6 @@
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<template> <template>
<template-type-parameter name="F"/> <template-type-parameter name="F"/>
@ -246,15 +237,6 @@
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions> <postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
<method name="swap"> <method name="swap">
<type>void</type> <type>void</type>
@ -626,15 +608,6 @@
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
@ -643,15 +616,6 @@
<throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws> <throws><simpara>Will not throw unless copying the target of <code>f</code> throws.</simpara></throws>
</constructor> </constructor>
<constructor>
<parameter name="f">
<paramtype><classname>function</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</constructor>
<constructor> <constructor>
<template> <template>
<template-type-parameter name="F"/> <template-type-parameter name="F"/>
@ -681,20 +645,11 @@
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>functionN</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
</parameter> </parameter>
<postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions> <postconditions><simpara>If copy construction does not throw, <code>*this</code> targets a copy of <code>f</code>'s target, if it has one, or is empty if <code>f.<methodname>empty</methodname>()</code>. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></postconditions>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>functionN</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<copy-assignment> <copy-assignment>
<parameter name="f"> <parameter name="f">
<paramtype>const <classname>function</classname>&amp;</paramtype> <paramtype>const <classname>function</classname>&amp;</paramtype>
@ -703,15 +658,6 @@
<throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws> <throws><simpara>Will not throw when the target of <code>f</code> is a stateless function object or a reference to the function object. If copy construction does throw, <code>this-&gt;<methodname>empty</methodname>()</code>.</simpara></throws>
</copy-assignment> </copy-assignment>
<copy-assignment>
<parameter name="f">
<paramtype><classname>function</classname>&amp;&amp;</paramtype>
</parameter>
<requires><simpara>C++11 compatible compiler.</simpara></requires>
<postconditions><simpara>Moves the value from <code>f</code> to <code>*this</code>. If the argument has its function object allocated on the heap, its buffer will be assigned to <code>*this</code> leaving argument empty.</simpara></postconditions>
<throws><simpara>Will not throw unless argument has its function object allocated not on the heap and copying the target of <code>f</code> throws.</simpara></throws>
</copy-assignment>
<method-group name="modifiers"> <method-group name="modifiers">
<method name="swap"> <method name="swap">
<type>void</type> <type>void</type>

View File

@ -35,12 +35,12 @@ form to use for your compiler.
<row> <row>
<entry> <entry>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><simpara>GNU C++ 2.95.x, 3.0.x and later versions</simpara></listitem> <listitem><simpara>GNU C++ 2.95.x, 3.0.x, 3.1.x</simpara></listitem>
<listitem><simpara>Comeau C++ 4.2.45.2</simpara></listitem> <listitem><simpara>Comeau C++ 4.2.45.2</simpara></listitem>
<listitem><simpara>SGI MIPSpro 7.3.0</simpara></listitem> <listitem><simpara>SGI MIPSpro 7.3.0</simpara></listitem>
<listitem><simpara>Intel C++ 5.0, 6.0</simpara></listitem> <listitem><simpara>Intel C++ 5.0, 6.0</simpara></listitem>
<listitem><simpara>Compaq's cxx 6.2</simpara></listitem> <listitem><simpara>Compaq's cxx 6.2</simpara></listitem>
<listitem><simpara>Microsoft Visual C++ 7.1 and later versions</simpara></listitem> <listitem><simpara>Microsoft Visual C++ 7.1</simpara></listitem>
</itemizedlist> </itemizedlist>
</entry> </entry>
<entry> <entry>

View File

@ -23,8 +23,8 @@
// in anything that may be included by function_template.hpp doesn't break // in anything that may be included by function_template.hpp doesn't break
#include <boost/function/detail/prologue.hpp> #include <boost/function/detail/prologue.hpp>
// Older Visual Age C++ version do not handle the file iteration well // Visual Age C++ doesn't handle the file iteration well
#if BOOST_WORKAROUND(__IBMCPP__, >= 500) && BOOST_WORKAROUND(__IBMCPP__, < 800) #if BOOST_WORKAROUND(__IBMCPP__, >= 500)
# if BOOST_FUNCTION_MAX_ARGS >= 0 # if BOOST_FUNCTION_MAX_ARGS >= 0
# include <boost/function/function0.hpp> # include <boost/function/function0.hpp>
# endif # endif

View File

@ -15,15 +15,10 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <new> #include <new>
#include <typeinfo>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <boost/type_index.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/composite_traits.hpp> #include <boost/type_traits/composite_traits.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
@ -35,7 +30,6 @@
# include "boost/mpl/bool.hpp" # include "boost/mpl/bool.hpp"
#endif #endif
#include <boost/function_equal.hpp> #include <boost/function_equal.hpp>
#include <boost/function/function_fwd.hpp>
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( push ) # pragma warning( push )
@ -43,16 +37,76 @@
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif #endif
#if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE
// Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS
#else
# define BOOST_FUNCTION_STD_NS std
#endif
// Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
|| defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips))
# include <cstring>
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
(std::strcmp((X).name(),(Y).name()) == 0)
# else
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#endif
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
#else #else
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // __ICL etc #endif // not MSVC
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
// Work around a compiler bug.
// boost::python::objects::function has to be seen by the compiler before the
// boost::function class template.
namespace boost { namespace python { namespace objects {
class function;
}}}
#endif
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
typename ::boost::enable_if_c< \ typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
!(::boost::is_integral<Functor>::value), \ (::boost::is_integral<Functor>::value)>::value), \
Type>::type Type>::type
#else
// BCC doesn't recognize this depends on a template argument and complains
// about the use of 'typename'
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
Type>::type
#endif
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost {
template<typename Signature>
class function;
template<typename Signature>
inline void swap(function<Signature>& f1,
function<Signature>& f2)
{
f1.swap(f2);
}
} // end namespace boost
#endif // have partial specialization
namespace boost { namespace boost {
namespace detail { namespace detail {
@ -65,26 +119,17 @@ namespace boost {
* object pointers, and a structure that resembles a bound * object pointers, and a structure that resembles a bound
* member function pointer. * member function pointer.
*/ */
union function_buffer_members union function_buffer
{ {
// For pointers to function objects // For pointers to function objects
typedef void* obj_ptr_t; void* obj_ptr;
mutable obj_ptr_t obj_ptr;
// For pointers to std::type_info objects // For pointers to std::type_info objects
struct type_t {
// (get_functor_type_tag, check_functor_type_tag). // (get_functor_type_tag, check_functor_type_tag).
const boost::typeindex::type_info* type; const void* const_obj_ptr;
// Whether the type is const-qualified.
bool const_qualified;
// Whether the type is volatile-qualified.
bool volatile_qualified;
} type;
// For function pointers of all kinds // For function pointers of all kinds
typedef void (*func_ptr_t)(); mutable void (*func_ptr)();
mutable func_ptr_t func_ptr;
// For bound member pointers // For bound member pointers
struct bound_memfunc_ptr_t { struct bound_memfunc_ptr_t {
@ -92,22 +137,8 @@ namespace boost {
void* obj_ptr; void* obj_ptr;
} bound_memfunc_ptr; } bound_memfunc_ptr;
// For references to function objects. We explicitly keep
// track of the cv-qualifiers on the object referenced.
struct obj_ref_t {
mutable void* obj_ptr;
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;
};
union function_buffer
{
// Type-specific union members
mutable function_buffer_members members;
// To relax aliasing constraints // To relax aliasing constraints
mutable char data[sizeof(function_buffer_members)]; mutable char data;
}; };
/** /**
@ -137,7 +168,6 @@ namespace boost {
// The operation type to perform on the given functor/function pointer // The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type { enum functor_manager_operation_type {
clone_functor_tag, clone_functor_tag,
move_functor_tag,
destroy_functor_tag, destroy_functor_tag,
check_functor_type_tag, check_functor_type_tag,
get_functor_type_tag get_functor_type_tag
@ -174,42 +204,34 @@ namespace boost {
struct reference_manager struct reference_manager
{ {
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, get(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
switch (op) { switch (op) {
case clone_functor_tag: case clone_functor_tag:
out_buffer.members.obj_ref = in_buffer.members.obj_ref; out_buffer.obj_ptr = in_buffer.obj_ptr;
return;
case move_functor_tag:
out_buffer.members.obj_ref = in_buffer.members.obj_ref;
in_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.members.obj_ref.obj_ptr = 0; out_buffer.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
// Check whether we have the same type. We can add // DPG TBD: Since we're only storing a pointer, it's
// cv-qualifiers, but we can't take them away. // possible that the user could ask for a base class or
if (*out_buffer.members.type.type == boost::typeindex::type_id<F>() // derived class. Is that okay?
&& (!in_buffer.members.obj_ref.is_const_qualified const BOOST_FUNCTION_STD_NS::type_info& check_type =
|| out_buffer.members.type.const_qualified) *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
&& (!in_buffer.members.obj_ref.is_volatile_qualified if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
|| out_buffer.members.type.volatile_qualified)) out_buffer.obj_ptr = in_buffer.obj_ptr;
out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info(); out_buffer.const_obj_ptr = &typeid(F);
out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -237,12 +259,6 @@ namespace boost {
A(a) A(a)
{ {
} }
functor_wrapper(const functor_wrapper& f) :
F(static_cast<const F&>(f)),
A(static_cast<const A&>(f))
{
}
}; };
/** /**
@ -260,21 +276,16 @@ namespace boost {
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.members.func_ptr = in_buffer.members.func_ptr; out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) { else if (op == destroy_functor_tag)
out_buffer.members.func_ptr = in_buffer.members.func_ptr; out_buffer.func_ptr = 0;
in_buffer.members.func_ptr = 0; else /* op == check_functor_type_tag */ {
} else if (op == destroy_functor_tag) const BOOST_FUNCTION_STD_NS::type_info& check_type =
out_buffer.members.func_ptr = 0; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
else if (op == check_functor_type_tag) { if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) out_buffer.obj_ptr = &in_buffer.func_ptr;
out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -283,30 +294,20 @@ namespace boost {
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag || op == move_functor_tag) { if (op == clone_functor_tag) {
const functor_type* in_functor = const functor_type* in_functor =
reinterpret_cast<const functor_type*>(in_buffer.data); reinterpret_cast<const functor_type*>(&in_buffer.data);
new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor); new ((void*)&out_buffer.data) functor_type(*in_functor);
if (op == move_functor_tag) {
functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor();
}
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data); reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
(void)f; // suppress warning about the value of f not being used (MSVC) } else /* op == check_functor_type_tag */ {
f->~Functor(); const BOOST_FUNCTION_STD_NS::type_info& check_type =
} else if (op == check_functor_type_tag) { *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.members.obj_ptr = in_buffer.data; out_buffer.obj_ptr = &in_buffer.data;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
} }
} }
}; };
@ -342,30 +343,23 @@ namespace boost {
// Clone the functor // Clone the functor
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
// jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete.
const functor_type* f = const functor_type* f =
static_cast<const functor_type*>(in_buffer.members.obj_ptr); (const functor_type*)(in_buffer.obj_ptr);
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
out_buffer.members.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */ /* Cast from the void pointer to the functor pointer type */
functor_type* f = functor_type* f =
static_cast<functor_type*>(out_buffer.members.obj_ptr); static_cast<functor_type*>(out_buffer.obj_ptr);
delete f; delete f;
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else /* op == check_functor_type_tag */ {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const BOOST_FUNCTION_STD_NS::type_info& check_type =
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -380,14 +374,6 @@ namespace boost {
mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>()); mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
} }
// For member pointers, we use the small-object optimization buffer.
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, member_ptr_tag)
{
manager(in_buffer, out_buffer, op, mpl::true_());
}
public: public:
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
@ -398,9 +384,7 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.const_obj_ptr = &typeid(functor_type);
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -447,34 +431,29 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
const functor_wrapper_type* f = const functor_wrapper_type* f =
static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr); (const functor_wrapper_type*)(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f); wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type // Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.members.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */ /* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim = functor_wrapper_type* victim =
static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr); static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else /* op == check_functor_type_tag */ {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const BOOST_FUNCTION_STD_NS::type_info& check_type =
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -499,9 +478,7 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.const_obj_ptr = &typeid(functor_type);
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -579,6 +556,7 @@ namespace boost {
*/ */
struct vtable_base struct vtable_base
{ {
vtable_base() : manager(0) { }
void (*manager)(const function_buffer& in_buffer, void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer, function_buffer& out_buffer,
functor_manager_operation_type op); functor_manager_operation_type op);
@ -600,15 +578,15 @@ public:
/** Determine if the function is empty (i.e., has no target). */ /** Determine if the function is empty (i.e., has no target). */
bool empty() const { return !vtable; } bool empty() const { return !vtable; }
/** Retrieve the type of the stored function object, or type_id<void>() /** Retrieve the type of the stored function object, or typeid(void)
if this is empty. */ if this is empty. */
const boost::typeindex::type_info& target_type() const const BOOST_FUNCTION_STD_NS::type_info& target_type() const
{ {
if (!vtable) return boost::typeindex::type_id<void>().type_info(); if (!vtable) return typeid(void);
detail::function::function_buffer type; detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); vtable->manager(functor, type, detail::function::get_functor_type_tag);
return *type.members.type.type; return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
} }
template<typename Functor> template<typename Functor>
@ -617,34 +595,38 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.const_obj_ptr = &typeid(Functor);
type_result.members.type.const_qualified = is_const<Functor>::value; vtable->manager(functor, type_result,
type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.members.obj_ptr); return static_cast<Functor*>(type_result.obj_ptr);
} }
template<typename Functor> template<typename Functor>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
const Functor* target( Functor * = 0 ) const
#else
const Functor* target() const const Functor* target() const
#endif
{ {
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.const_obj_ptr = &typeid(Functor);
type_result.members.type.const_qualified = true; vtable->manager(functor, type_result,
type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
return static_cast<const Functor*>(type_result.members.obj_ptr); return (const Functor*)(type_result.obj_ptr);
} }
template<typename F> template<typename F>
bool contains(const F& f) const bool contains(const F& f) const
{ {
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
if (const F* fp = this->target( (F*)0 ))
#else
if (const F* fp = this->template target<F>()) if (const F* fp = this->template target<F>())
#endif
{ {
return function_equal(*fp, f); return function_equal(*fp, f);
} else { } else {
@ -676,15 +658,6 @@ public:
#endif #endif
public: // should be protected, but GCC 2.95.3 will fail to allow access public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::vtable_base* get_vtable() const {
return reinterpret_cast<detail::function::vtable_base*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
}
bool has_trivial_copy_and_destroy() const {
return reinterpret_cast<std::size_t>(vtable) & 0x01;
}
detail::function::vtable_base* vtable; detail::function::vtable_base* vtable;
mutable detail::function::function_buffer functor; mutable detail::function::function_buffer functor;
}; };
@ -858,9 +831,6 @@ namespace detail {
} // end namespace boost } // end namespace boost
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif
#endif // BOOST_FUNCTION_BASE_HEADER #endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -1,69 +0,0 @@
// Boost.Function library
// Copyright (C) Douglas Gregor 2008
//
// 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)
//
// For more information, see http://www.boost.org
#ifndef BOOST_FUNCTION_FWD_HPP
#define BOOST_FUNCTION_FWD_HPP
#include <boost/config.hpp>
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
// Work around a compiler bug.
// boost::python::objects::function has to be seen by the compiler before the
// boost::function class template.
namespace boost { namespace python { namespace objects {
class function;
}}}
#endif
#if defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif
namespace boost {
class bad_function_call;
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
// Preferred syntax
template<typename Signature> class function;
template<typename Signature>
inline void swap(function<Signature>& f1, function<Signature>& f2)
{
f1.swap(f2);
}
#endif // have partial specialization
// Portable syntax
template<typename R> class function0;
template<typename R, typename T1> class function1;
template<typename R, typename T1, typename T2> class function2;
template<typename R, typename T1, typename T2, typename T3> class function3;
template<typename R, typename T1, typename T2, typename T3, typename T4>
class function4;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5>
class function5;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
class function6;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
class function7;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
class function8;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
class function9;
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9,
typename T10>
class function10;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,45 +0,0 @@
// Boost.Function library - Typeof support
// Copyright (C) Douglas Gregor 2008
//
// 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)
//
// For more information, see http://www.boost.org
#ifndef BOOST_FUNCTION_TYPEOF_HPP
#define BOOST_FUNCTION_TYPEOF_HPP
#include <boost/function/function_fwd.hpp>
#include <boost/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
BOOST_TYPEOF_REGISTER_TYPE(boost::bad_function_call)
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, (typename))
#endif
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function0, (typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function1, (typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function2, (typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function3,
(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function4,
(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function5,
(typename)(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function6,
(typename)(typename)(typename)(typename)(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function7,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function8,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function9,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename)(typename))
BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function10,
(typename)(typename)(typename)(typename)(typename)(typename)(typename)
(typename)(typename)(typename)(typename))
#endif

View File

@ -1,18 +0,0 @@
{
"key": "function",
"name": "Function",
"authors": [
"Doug Gregor"
],
"description": "Function object wrappers for deferred calls or callbacks.",
"std": [
"tr1"
],
"category": [
"Function-objects",
"Programming"
],
"maintainers": [
"Douglas Gregor <dgregor -at- cs.indiana.edu>"
]
}

View File

@ -8,7 +8,6 @@
# For more information, see http://www.boost.org/ # For more information, see http://www.boost.org/
project project
: requirements <toolset>msvc:<asynch-exceptions>on
: source-location $(BOOST_ROOT) : source-location $(BOOST_ROOT)
; ;
@ -21,8 +20,6 @@ import testing ;
: :
[ run libs/function/test/function_test.cpp : : : : lib_function_test ] [ run libs/function/test/function_test.cpp : : : : lib_function_test ]
[ run libs/function/test/function_test.cpp : : : <rtti>off : lib_function_test_no_rtti ]
[ run libs/function/test/function_n_test.cpp : : : : ] [ run libs/function/test/function_n_test.cpp : : : : ]
[ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ]
@ -61,11 +58,6 @@ import testing ;
[ run libs/function/test/contains2_test.cpp : : : : ] [ run libs/function/test/contains2_test.cpp : : : : ]
[ run libs/function/test/nothrow_swap.cpp : : : : ]
[ run libs/function/test/rvalues_test.cpp : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ]
; ;
} }

View File

@ -129,9 +129,5 @@ test_main(int, char*[])
fv.assign( &do_nothing, std::allocator<int>() ); fv.assign( &do_nothing, std::allocator<int>() );
fv.clear(); fv.clear();
function0<void> fv2;
fv.assign(&do_nothing, std::allocator<int>() );
fv2.assign(fv, std::allocator<int>() );
return 0; return 0;
} }

View File

@ -88,15 +88,6 @@ static void target_test()
BOOST_CHECK(!f.target<int (*)()>()); BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<Seventeen>()); BOOST_CHECK(f.target<Seventeen>());
BOOST_CHECK(f.target<Seventeen>() == &this_seventeen); BOOST_CHECK(f.target<Seventeen>() == &this_seventeen);
const Seventeen const_seventeen = this_seventeen;
f = boost::ref(const_seventeen);
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<const Seventeen>());
BOOST_CHECK(f.target<const Seventeen>() == &const_seventeen);
BOOST_CHECK(f.target<const volatile Seventeen>());
BOOST_CHECK(!f.target<Seventeen>());
BOOST_CHECK(!f.target<volatile Seventeen>());
} }
static void equal_test() static void equal_test()

View File

@ -636,54 +636,6 @@ test_ref()
} }
} }
static unsigned construction_count = 0;
static unsigned destruction_count = 0;
struct MySmallFunctor {
MySmallFunctor() { ++construction_count; }
MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
~MySmallFunctor() { ++destruction_count; }
int operator()() { return 0; }
};
struct MyLargeFunctor {
MyLargeFunctor() { ++construction_count; }
MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
~MyLargeFunctor() { ++destruction_count; }
int operator()() { return 0; }
float data[128];
};
void test_construct_destroy_count()
{
{
boost::function0<int> f;
boost::function0<int> g;
f = MySmallFunctor();
g = MySmallFunctor();
f.swap(g);
}
// MySmallFunctor objects should be constructed as many times as
// they are destroyed.
BOOST_CHECK(construction_count == destruction_count);
construction_count = 0;
destruction_count = 0;
{
boost::function0<int> f;
boost::function0<int> g;
f = MyLargeFunctor();
g = MyLargeFunctor();
f.swap(g);
}
// MyLargeFunctor objects should be constructed as many times as
// they are destroyed.
BOOST_CHECK(construction_count == destruction_count);
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_zero_args(); test_zero_args();
@ -692,6 +644,5 @@ int test_main(int, char* [])
test_emptiness(); test_emptiness();
test_member_functions(); test_member_functions();
test_ref(); test_ref();
test_construct_destroy_count();
return 0; return 0;
} }

View File

@ -13,8 +13,8 @@
#include <string> #include <string>
#include <utility> #include <utility>
using boost::function; using namespace boost;
using std::string; using namespace std;
int global_int; int global_int;
@ -525,7 +525,7 @@ test_zero_args()
static void static void
test_one_arg() test_one_arg()
{ {
std::negate<int> neg; negate<int> neg;
function<int (int)> f1(neg); function<int (int)> f1(neg);
BOOST_CHECK(f1(5) == -5); BOOST_CHECK(f1(5) == -5);
@ -607,12 +607,12 @@ struct add_with_throw_on_copy {
add_with_throw_on_copy(const add_with_throw_on_copy&) add_with_throw_on_copy(const add_with_throw_on_copy&)
{ {
throw std::runtime_error("But this CAN'T throw"); throw runtime_error("But this CAN'T throw");
} }
add_with_throw_on_copy& operator=(const add_with_throw_on_copy&) add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
{ {
throw std::runtime_error("But this CAN'T throw"); throw runtime_error("But this CAN'T throw");
} }
}; };
@ -621,38 +621,14 @@ test_ref()
{ {
add_with_throw_on_copy atc; add_with_throw_on_copy atc;
try { try {
boost::function<int (int, int)> f(boost::ref(atc)); boost::function<int (int, int)> f(ref(atc));
BOOST_CHECK(f(1, 3) == 4); BOOST_CHECK(f(1, 3) == 4);
} }
catch(std::runtime_error e) { catch(runtime_error e) {
BOOST_ERROR("Nonthrowing constructor threw an exception"); BOOST_ERROR("Nonthrowing constructor threw an exception");
} }
} }
static void dummy() {}
static void test_empty_ref()
{
boost::function<void()> f1;
boost::function<void()> f2(boost::ref(f1));
try {
f2();
BOOST_ERROR("Exception didn't throw for reference to empty function.");
}
catch(std::runtime_error e) {}
f1 = dummy;
try {
f2();
}
catch(std::runtime_error e) {
BOOST_ERROR("Error calling referenced function.");
}
}
static void test_exception() static void test_exception()
{ {
boost::function<int (int, int)> f; boost::function<int (int, int)> f;
@ -690,95 +666,6 @@ static void test_call()
test_call_cref(std::plus<int>()); test_call_cref(std::plus<int>());
} }
struct big_aggregating_structure {
int disable_small_objects_optimizations[32];
big_aggregating_structure()
{
++ global_int;
}
big_aggregating_structure(const big_aggregating_structure&)
{
++ global_int;
}
~big_aggregating_structure()
{
-- global_int;
}
void operator()()
{
++ global_int;
}
void operator()(int)
{
++ global_int;
}
};
template <class FunctionT>
static void test_move_semantics()
{
typedef FunctionT f1_type;
big_aggregating_structure obj;
f1_type f1 = obj;
global_int = 0;
f1();
BOOST_CHECK(!f1.empty());
BOOST_CHECK(global_int == 1);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Testing rvalue constructors
f1_type f2(static_cast<f1_type&&>(f1));
BOOST_CHECK(f1.empty());
BOOST_CHECK(!f2.empty());
BOOST_CHECK(global_int == 1);
f2();
BOOST_CHECK(global_int == 2);
f1_type f3(static_cast<f1_type&&>(f2));
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(!f3.empty());
BOOST_CHECK(global_int == 2);
f3();
BOOST_CHECK(global_int == 3);
// Testing move assignment
f1_type f4;
BOOST_CHECK(f4.empty());
f4 = static_cast<f1_type&&>(f3);
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(f3.empty());
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 3);
f4();
BOOST_CHECK(global_int == 4);
// Testing self move assignment
f4 = static_cast<f1_type&&>(f4);
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
// Testing, that no memory leaked when assigning to nonempty function
f4 = obj;
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
f1_type f5 = obj;
BOOST_CHECK(global_int == 5);
f4 = static_cast<f1_type&&>(f5);
BOOST_CHECK(global_int == 4);
#endif
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_zero_args(); test_zero_args();
@ -787,12 +674,9 @@ int test_main(int, char* [])
test_emptiness(); test_emptiness();
test_member_functions(); test_member_functions();
test_ref(); test_ref();
test_empty_ref();
test_exception(); test_exception();
test_implicit(); test_implicit();
test_call(); test_call();
test_move_semantics<function<void()> >();
test_move_semantics<boost::function0<void> >();
return 0; return 0;
} }

View File

@ -1,18 +0,0 @@
// Boost.Function library
// Copyright Douglas Gregor 2008. 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)
// For more information, see http://www.boost.org
#include <boost/function/function_typeof.hpp>
#include <boost/function.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
void f(boost::function0<void> f, boost::function0<void> g)
{
BOOST_STATIC_ASSERT((boost::is_same<boost::function0<void>, BOOST_TYPEOF(f = g)>::value));
}

View File

@ -15,21 +15,21 @@
#include <boost/lambda/bind.hpp> #include <boost/lambda/bind.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
using namespace std;
using namespace boost;
using namespace boost::lambda;
static unsigned static unsigned
func_impl(int arg1, bool arg2, double arg3) func_impl(int arg1, bool arg2, double arg3)
{ {
using namespace std;
return abs (static_cast<int>((arg2 ? arg1 : 2 * arg1) * arg3)); return abs (static_cast<int>((arg2 ? arg1 : 2 * arg1) * arg3));
} }
int test_main(int, char*[]) int test_main(int, char*[])
{ {
using boost::function;
using namespace boost::lambda;
function <unsigned(bool, double)> f1 = bind(func_impl, 15, _1, _2); function <unsigned(bool, double)> f1 = bind(func_impl, 15, _1, _2);
function <unsigned(double)> f2 = boost::lambda::bind(f1, false, _1); function <unsigned(double)> f2 = bind(f1, false, _1);
function <unsigned()> f3 = boost::lambda::bind(f2, 4.0); function <unsigned()> f3 = bind(f2, 4.0);
f3(); f3();

View File

@ -10,36 +10,22 @@
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
Y& foo2(Y&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
Y& X::foo2(Y& x) const { return x; }
int main() int main()
{ {
boost::function<int (X*, int)> f; boost::function<int (X*, int)> f;
boost::function<Y& (X*, Y&)> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); f(&x, 5);
BOOST_TEST(f2(&x, boost::ref(y1)) == y1);
return ::boost::report_errors(); return 0;
} }

View File

@ -10,36 +10,22 @@
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
Y& foo2(Y&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
Y& X::foo2(Y& x) const { return x; }
int main() int main()
{ {
boost::function2<int, X*, int> f; boost::function2<int, X*, int> f;
boost::function2<Y&, X*, Y&> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); f(&x, 5);
BOOST_TEST(f2(&x, boost::ref(y1)) == y1);
return ::boost::report_errors(); return 0;
} }

View File

@ -1,60 +0,0 @@
// Boost.Function library
// Copyright Douglas Gregor 2008. 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)
// For more information, see http://www.boost.org
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
struct tried_to_copy { };
struct MaybeThrowOnCopy {
MaybeThrowOnCopy(int value = 0) : value(value) { }
MaybeThrowOnCopy(const MaybeThrowOnCopy& other) : value(other.value) {
if (throwOnCopy)
throw tried_to_copy();
}
MaybeThrowOnCopy& operator=(const MaybeThrowOnCopy& other) {
if (throwOnCopy)
throw tried_to_copy();
value = other.value;
return *this;
}
int operator()() { return value; }
int value;
// Make sure that this function object doesn't trigger the
// small-object optimization in Function.
float padding[100];
static bool throwOnCopy;
};
bool MaybeThrowOnCopy::throwOnCopy = false;
int test_main(int, char* [])
{
boost::function0<int> f;
boost::function0<int> g;
MaybeThrowOnCopy::throwOnCopy = false;
f = MaybeThrowOnCopy(1);
g = MaybeThrowOnCopy(2);
BOOST_CHECK(f() == 1);
BOOST_CHECK(g() == 2);
MaybeThrowOnCopy::throwOnCopy = true;
f.swap(g);
BOOST_CHECK(f() == 2);
BOOST_CHECK(g() == 1);
return 0;
}

View File

@ -1,106 +0,0 @@
// Copyright 2014 Antony Polukhin.
//
// 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)
// For more information, see http://www.boost.org
#include <iostream>
#include <cstdlib>
#include <boost/test/minimal.hpp>
#include <boost/function.hpp>
#include <boost/move/move.hpp>
class only_movable {
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(only_movable)
int value_;
bool moved_;
public:
only_movable(BOOST_RV_REF(only_movable) x)
: value_(x.value_)
, moved_(false)
{
x.moved_ = true;
}
only_movable& operator=(BOOST_RV_REF(only_movable) x) {
value_ = x.value_;
x.moved_ = true;
moved_ = false;
return *this;
}
explicit only_movable(int value = 0) : value_(value), moved_(false) {}
int get_value() const { return value_; }
bool is_moved() const { return moved_; }
};
int one(BOOST_RV_REF(only_movable) v) { return v.get_value(); }
only_movable two(BOOST_RV_REF(only_movable) t) {
only_movable t1 = boost::move(t);
return BOOST_MOVE_RET(only_movable, t1);
}
only_movable two_sum(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) {
only_movable ret(t1.get_value() + t2.get_value());
return BOOST_MOVE_RET(only_movable, ret);
}
struct sum_struct {
only_movable operator()(BOOST_RV_REF(only_movable) t1, BOOST_RV_REF(only_movable) t2) const {
only_movable ret(t1.get_value() + t2.get_value());
return BOOST_MOVE_RET(only_movable, ret);
}
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
int three(std::string&&) { return 1; }
std::string&& four(std::string&& s) { return boost::move(s); }
#endif
int test_main(int, char*[])
{
using boost::function;
function <int(BOOST_RV_REF(only_movable))> f1 = one;
only_movable om1(1);
BOOST_CHECK(f1(boost::move(om1)) == 1);
function <only_movable(BOOST_RV_REF(only_movable))> f2 = two;
only_movable om2(2);
only_movable om2_2 = f2(boost::move(om2));
BOOST_CHECK(om2_2.get_value() == 2);
BOOST_CHECK(om2.is_moved());
{
function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = two_sum;
only_movable om1_sum(1), om2_sum(2);
only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
BOOST_CHECK(om2_sum_2.get_value() == 3);
}
{
sum_struct s;
function <only_movable(BOOST_RV_REF(only_movable), BOOST_RV_REF(only_movable))> f2_sum = s;
only_movable om1_sum(1), om2_sum(2);
only_movable om2_sum_2 = f2_sum(boost::move(om1_sum), boost::move(om2_sum));
BOOST_CHECK(om2_sum_2.get_value() == 3);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
function <int(std::string&&)> f3 = three;
function <std::string&& (std::string&& s)> f4 = four;
f3(std::string("Hello"));
BOOST_CHECK(f4(std::string("world")) == "world");
#endif
return 0;
}