Compare commits

..

1 Commits

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

View File

@ -6,11 +6,5 @@
project boost/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,26 +13,6 @@
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<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

@ -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,17 +15,11 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <new> #include <new>
#include <typeinfo>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/integer.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/type_traits/ice.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
@ -36,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 )
@ -45,7 +38,7 @@
#endif #endif
// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info. // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
#ifdef BOOST_NO_STD_TYPEINFO #ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE
// Embedded VC++ does not have type_info in namespace std // Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS # define BOOST_FUNCTION_STD_NS
#else #else
@ -54,9 +47,7 @@
// Borrowed from Boost.Python library: determines the cases where we // Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==. // need to use std::type_info::name to compare instead of operator==.
#if defined( BOOST_NO_TYPEID ) # if (defined(__GNUC__) && __GNUC__ >= 3) \
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#elif (defined(__GNUC__) && __GNUC__ >= 3) \
|| defined(_AIX) \ || defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips)) || ( defined(__sgi) && defined(__host_mips))
# include <cstring> # include <cstring>
@ -72,7 +63,22 @@
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // not MSVC #endif // not MSVC
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0) #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<(::boost::type_traits::ice_not< \ typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \ (::boost::is_integral<Functor>::value)>::value), \
@ -86,6 +92,22 @@
Type>::type Type>::type
#endif #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 {
namespace function { namespace function {
@ -100,18 +122,11 @@ namespace boost {
union function_buffer union function_buffer
{ {
// For pointers to function objects // For pointers to function objects
mutable void* obj_ptr; void* 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 void* const_obj_ptr;
const detail::sp_typeinfo* type;
// 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
mutable void (*func_ptr)(); mutable void (*func_ptr)();
@ -122,14 +137,6 @@ 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;
// To relax aliasing constraints // To relax aliasing constraints
mutable char data; mutable char data;
}; };
@ -161,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
@ -198,45 +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.obj_ref = in_buffer.obj_ref; out_buffer.obj_ptr = in_buffer.obj_ptr;
return;
case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref;
in_buffer.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0; out_buffer.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
const detail::sp_typeinfo& check_type // DPG TBD: Since we're only storing a pointer, it's
= *out_buffer.type.type; // possible that the user could ask for a base class or
// derived class. Is that okay?
// Check whether we have the same type. We can add const BOOST_FUNCTION_STD_NS::type_info& check_type =
// cv-qualifiers, but we can't take them away. *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F)) if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
&& (!in_buffer.obj_ref.is_const_qualified out_buffer.obj_ptr = in_buffer.obj_ptr;
|| out_buffer.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &BOOST_SP_TYPEID(F); out_buffer.const_obj_ptr = &typeid(F);
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -264,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))
{
}
}; };
/** /**
@ -288,22 +277,15 @@ namespace boost {
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) { else if (op == destroy_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.func_ptr = 0;
} else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0; out_buffer.func_ptr = 0;
else if (op == check_functor_type_tag) { else /* op == check_functor_type_tag */ {
const detail::sp_typeinfo& check_type const BOOST_FUNCTION_STD_NS::type_info& check_type =
= *out_buffer.type.type; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr; out_buffer.obj_ptr = &in_buffer.func_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
} }
} }
@ -312,32 +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);
const detail::sp_typeinfo& check_type if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = &in_buffer.data; out_buffer.obj_ptr = &in_buffer.data;
else else
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
} }
} }
}; };
@ -373,32 +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.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.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.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.obj_ptr); static_cast<functor_type*>(out_buffer.obj_ptr);
delete f; delete f;
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else /* op == check_functor_type_tag */ {
const detail::sp_typeinfo& check_type const BOOST_FUNCTION_STD_NS::type_info& check_type =
= *out_buffer.type.type; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
} }
} }
@ -413,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. */
@ -431,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.type.type = &BOOST_SP_TYPEID(functor_type); out_buffer.const_obj_ptr = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return; return;
default: default:
@ -480,7 +431,7 @@ 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.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);
@ -488,9 +439,6 @@ namespace boost {
// 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.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.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 =
@ -499,17 +447,13 @@ namespace boost {
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else /* op == check_functor_type_tag */ {
const detail::sp_typeinfo& check_type const BOOST_FUNCTION_STD_NS::type_info& check_type =
= *out_buffer.type.type; *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor))) if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
} }
} }
@ -534,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.type.type = &BOOST_SP_TYPEID(functor_type); out_buffer.const_obj_ptr = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return; return;
default: default:
@ -614,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);
@ -635,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 BOOST_SP_TYPEID(void) /** Retrieve the type of the stored function object, or typeid(void)
if this is empty. */ if this is empty. */
const detail::sp_typeinfo& target_type() const const BOOST_FUNCTION_STD_NS::type_info& target_type() const
{ {
if (!vtable) return BOOST_SP_TYPEID(void); 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.type.type; return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
} }
template<typename Functor> template<typename Functor>
@ -652,10 +595,8 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &BOOST_SP_TYPEID(Functor); type_result.const_obj_ptr = &typeid(Functor);
type_result.type.const_qualified = is_const<Functor>::value; vtable->manager(functor, type_result,
type_result.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.obj_ptr); return static_cast<Functor*>(type_result.obj_ptr);
} }
@ -670,14 +611,12 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &BOOST_SP_TYPEID(Functor); type_result.const_obj_ptr = &typeid(Functor);
type_result.type.const_qualified = true; vtable->manager(functor, type_result,
type_result.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.obj_ptr); return (const Functor*)(type_result.obj_ptr);
} }
template<typename F> template<typename F>
@ -719,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;
}; };
@ -903,8 +833,4 @@ namespace detail {
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID #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,70 +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_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| 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

View File

@ -11,7 +11,6 @@
// Note: this header is a header template and must NOT have multiple-inclusion // Note: this header is a header template and must NOT have multiple-inclusion
// protection. // protection.
#include <boost/function/detail/prologue.hpp> #include <boost/function/detail/prologue.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( push ) # pragma warning( push )
@ -54,20 +53,12 @@
BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_MEMBER_INVOKER \
BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_MEMBER_INVOKER \
BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_INVOKER \
BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
#ifndef BOOST_NO_VOID_RETURNS #ifndef BOOST_NO_VOID_RETURNS
@ -189,44 +180,6 @@ namespace boost {
} }
}; };
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Handle invocation of member pointers. */
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_MEMBER_INVOKER
{
static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
}
};
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
{
static BOOST_FUNCTION_VOID_RETURN_TYPE
invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS)
{
MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
}
};
#endif
template< template<
typename FunctionPtr, typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
@ -290,190 +243,11 @@ namespace boost {
>::type type; >::type type;
}; };
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Retrieve the appropriate invoker for a member pointer. */
template<
typename MemberPtr,
typename R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_PARMS
>
struct BOOST_FUNCTION_GET_MEMBER_INVOKER
{
typedef typename mpl::if_c<(is_void<R>::value),
BOOST_FUNCTION_VOID_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>,
BOOST_FUNCTION_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>
>::type type;
};
#endif
/* Given the tag returned by get_function_tag, retrieve the
actual invoker that will be used for the given function
object.
Each specialization contains an "apply" nested class template
that accepts the function object, return type, function
argument types, and allocator. The resulting "apply" class
contains two typedefs, "invoker_type" and "manager_type",
which correspond to the invoker and manager types. */
template<typename Tag>
struct BOOST_FUNCTION_GET_INVOKER { };
/* Retrieve the invoker for a function pointer. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
{
template<typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<FunctionPtr> manager_type;
};
template<typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply_a
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<FunctionPtr> manager_type;
};
};
#if BOOST_FUNCTION_NUM_ARGS > 0
/* Retrieve the invoker for a member pointer. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
{
template<typename MemberPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct apply
{
typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<MemberPtr> manager_type;
};
template<typename MemberPtr,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply_a
{
typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
MemberPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<MemberPtr> manager_type;
};
};
#endif
/* Retrieve the invoker for a function object. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
{
template<typename FunctionObj,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager<FunctionObj> manager_type;
};
template<typename FunctionObj,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply_a
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef functor_manager_a<FunctionObj, Allocator> manager_type;
};
};
/* Retrieve the invoker for a reference to a function object. */
template<>
struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
{
template<typename RefWrapper,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct apply
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
typename RefWrapper::type,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef reference_manager<typename RefWrapper::type> manager_type;
};
template<typename RefWrapper,
typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
typename Allocator>
struct apply_a
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
typename RefWrapper::type,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type;
typedef reference_manager<typename RefWrapper::type> manager_type;
};
};
/** /**
* vtable for a specific boost::function instance. This * vtable for a specific boost::function instance.
* structure must be an aggregate so that we can use static
* initialization in boost::function's assign_to and assign_to_a
* members. It therefore cannot have any constructors,
* destructors, base classes, etc.
*/ */
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
struct BOOST_FUNCTION_VTABLE struct BOOST_FUNCTION_VTABLE : vtable_base
{ {
#ifndef BOOST_NO_VOID_RETURNS #ifndef BOOST_NO_VOID_RETURNS
typedef R result_type; typedef R result_type;
@ -486,35 +260,86 @@ namespace boost {
BOOST_FUNCTION_TEMPLATE_ARGS); BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename F> template<typename F>
bool assign_to(F f, function_buffer& functor) const BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
{
init(f);
}
template<typename F,typename Allocator>
BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
{
init_a<Allocator>(f);
}
template<typename F>
bool assign_to(F f, function_buffer& functor)
{ {
typedef typename get_function_tag<F>::type tag; typedef typename get_function_tag<F>::type tag;
return assign_to(f, functor, tag()); return assign_to(f, functor, tag());
} }
template<typename F,typename Allocator> template<typename F,typename Allocator>
bool assign_to_a(F f, function_buffer& functor, Allocator a) const bool assign_to_a(F f, function_buffer& functor, Allocator a)
{ {
typedef typename get_function_tag<F>::type tag; typedef typename get_function_tag<F>::type tag;
return assign_to_a(f, functor, a, tag()); return assign_to_a(f, functor, a, tag());
} }
void clear(function_buffer& functor) const void clear(function_buffer& functor)
{ {
if (base.manager) if (manager)
base.manager(functor, functor, destroy_functor_tag); manager(functor, functor, destroy_functor_tag);
} }
private: private:
template<typename F>
void init(F f)
{
typedef typename get_function_tag<F>::type tag;
init(f, tag());
}
template<typename Allocator,typename F>
void init_a(F f)
{
typedef typename get_function_tag<F>::type tag;
init_a<Allocator>(f, tag());
}
// Function pointers // Function pointers
template<typename FunctionPtr>
void init(FunctionPtr /*f*/, function_ptr_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager<FunctionPtr>::manage;
}
template<typename Allocator,typename FunctionPtr>
void init_a(FunctionPtr f, function_ptr_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
FunctionPtr,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
}
template<typename FunctionPtr> template<typename FunctionPtr>
bool bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
{ {
this->clear(functor); this->clear(functor);
if (f) { if (f) {
// should be a reinterpret cast, but some compilers insist // should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions // on giving cv-qualifiers to free functions
functor.func_ptr = reinterpret_cast<void (*)()>(f); functor.func_ptr = (void (*)())(f);
return true; return true;
} else { } else {
return false; return false;
@ -522,7 +347,7 @@ namespace boost {
} }
template<typename FunctionPtr,typename Allocator> template<typename FunctionPtr,typename Allocator>
bool bool
assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
{ {
return assign_to(f,functor,function_ptr_tag()); return assign_to(f,functor,function_ptr_tag());
} }
@ -530,26 +355,43 @@ namespace boost {
// Member pointers // Member pointers
#if BOOST_FUNCTION_NUM_ARGS > 0 #if BOOST_FUNCTION_NUM_ARGS > 0
template<typename MemberPtr> template<typename MemberPtr>
bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const void init(MemberPtr f, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
this->init(mem_fn(f));
}
template<typename Allocator,typename MemberPtr>
void init_a(MemberPtr f, member_ptr_tag)
{
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
this->init_a<Allocator>(mem_fn(f));
}
template<typename MemberPtr>
bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
{ {
// DPG TBD: Add explicit support for member function // DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the // objects, so we invoke through mem_fn() but we retain the
// right target_type() values. // right target_type() values.
if (f) { if (f) {
this->assign_to(boost::mem_fn(f), functor); this->assign_to(mem_fn(f), functor);
return true; return true;
} else { } else {
return false; return false;
} }
} }
template<typename MemberPtr,typename Allocator> template<typename MemberPtr,typename Allocator>
bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
{ {
// DPG TBD: Add explicit support for member function // DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the // objects, so we invoke through mem_fn() but we retain the
// right target_type() values. // right target_type() values.
if (f) { if (f) {
this->assign_to_a(boost::mem_fn(f), functor, a); this->assign_to_a(mem_fn(f), functor, a);
return true; return true;
} else { } else {
return false; return false;
@ -558,16 +400,43 @@ namespace boost {
#endif // BOOST_FUNCTION_NUM_ARGS > 0 #endif // BOOST_FUNCTION_NUM_ARGS > 0
// Function objects // Function objects
template<typename FunctionObj>
void init(FunctionObj /*f*/, function_obj_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager<FunctionObj>::manage;
}
template<typename Allocator,typename FunctionObj>
void init_a(FunctionObj /*f*/, function_obj_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &functor_manager_a<FunctionObj, Allocator>::manage;
}
// Assign to a function object using the small object optimization // Assign to a function object using the small object optimization
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
{ {
new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f); new ((void*)&functor.data) FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
{ {
assign_functor(f,functor,mpl::true_()); assign_functor(f,functor,mpl::true_());
} }
@ -575,13 +444,13 @@ namespace boost {
// Assign to a function object allocated on the heap. // Assign to a function object allocated on the heap.
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
{ {
functor.obj_ptr = new FunctionObj(f); functor.obj_ptr = new FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
{ {
typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
typedef typename Allocator::template rebind<functor_wrapper_type>::other typedef typename Allocator::template rebind<functor_wrapper_type>::other
@ -596,7 +465,7 @@ namespace boost {
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor, assign_functor(f, functor,
@ -608,7 +477,7 @@ namespace boost {
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor_a(f, functor, a, assign_functor_a(f, functor, a,
@ -620,26 +489,52 @@ namespace boost {
} }
// Reference to a function object // Reference to a function object
template<typename FunctionObj>
void
init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
{
typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
FunctionObj,
R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS
>::type
actual_invoker_type;
invoker = &actual_invoker_type::invoke;
manager = &reference_manager<FunctionObj>::get;
}
template<typename Allocator,typename FunctionObj>
void
init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
{
init(f,function_obj_ref_tag());
}
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(const reference_wrapper<FunctionObj>& f, assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const function_buffer& functor, function_obj_ref_tag)
{ {
functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); if (!boost::detail::function::has_empty_target(f.get_pointer())) {
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value; // DPG TBD: We might need to detect constness of
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; // FunctionObj to assign into obj_ptr or const_obj_ptr to
return true; // be truly legit, but no platform in existence makes
// const void* different from void*.
functor.const_obj_ptr = f.get_pointer();
return true;
} else {
return false;
}
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(const reference_wrapper<FunctionObj>& f, assign_to_a(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, Allocator, function_obj_ref_tag) const function_buffer& functor, Allocator, function_obj_ref_tag)
{ {
return assign_to(f,functor,function_obj_ref_tag()); return assign_to(f,functor,function_obj_ref_tag());
} }
public: public:
vtable_base base;
invoker_type invoker; invoker_type invoker;
}; };
} // end namespace function } // end namespace function
@ -675,11 +570,6 @@ namespace boost {
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
vtable_type; vtable_type;
vtable_type* get_vtable() const {
return reinterpret_cast<vtable_type*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<size_t>(0x01));
}
struct clear_type {}; struct clear_type {};
public: public:
@ -751,14 +641,20 @@ namespace boost {
~BOOST_FUNCTION_FUNCTION() { clear(); } ~BOOST_FUNCTION_FUNCTION() { clear(); }
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
// MSVC 6.0 and prior require all definitions to be inline, but
// these definitions can become very costly.
result_type operator()(BOOST_FUNCTION_PARMS) const result_type operator()(BOOST_FUNCTION_PARMS) const
{ {
if (this->empty()) if (this->empty())
boost::throw_exception(bad_function_call()); boost::throw_exception(bad_function_call());
return get_vtable()->invoker return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
} }
#else
result_type operator()(BOOST_FUNCTION_PARMS) const;
#endif
// The distinction between when to use BOOST_FUNCTION_FUNCTION and // The distinction between when to use BOOST_FUNCTION_FUNCTION and
// when to use self_type is obnoxious. MSVC cannot handle self_type as // when to use self_type is obnoxious. MSVC cannot handle self_type as
@ -777,26 +673,24 @@ namespace boost {
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{ {
this->clear(); this->clear();
BOOST_TRY { try {
this->assign_to(f); this->assign_to(f);
} BOOST_CATCH (...) { } catch (...) {
vtable = 0; vtable = 0;
BOOST_RETHROW; throw;
} }
BOOST_CATCH_END
return *this; return *this;
} }
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a) void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
{ {
this->clear(); this->clear();
BOOST_TRY{ try {
this->assign_to_a(f,a); this->assign_to_a(f,a);
} BOOST_CATCH (...) { } catch (...) {
vtable = 0; vtable = 0;
BOOST_RETHROW; throw;
} }
BOOST_CATCH_END
} }
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
@ -821,13 +715,12 @@ namespace boost {
return *this; return *this;
this->clear(); this->clear();
BOOST_TRY { try {
this->assign_to_own(f); this->assign_to_own(f);
} BOOST_CATCH (...) { } catch (...) {
vtable = 0; vtable = 0;
BOOST_RETHROW; throw;
} }
BOOST_CATCH_END
return *this; return *this;
} }
@ -836,18 +729,16 @@ namespace boost {
if (&other == this) if (&other == this)
return; return;
BOOST_FUNCTION_FUNCTION tmp; BOOST_FUNCTION_FUNCTION tmp = *this;
tmp.move_assign(*this); *this = other;
this->move_assign(other); other = tmp;
other.move_assign(tmp);
} }
// Clear out a target, if there is one // Clear out a target, if there is one
void clear() void clear()
{ {
if (vtable) { if (vtable) {
if (!this->has_trivial_copy_and_destroy()) static_cast<vtable_type*>(vtable)->clear(this->functor);
get_vtable()->clear(this->functor);
vtable = 0; vtable = 0;
} }
} }
@ -858,7 +749,7 @@ namespace boost {
#else #else
private: private:
struct dummy { struct dummy {
void nonnull() {} void nonnull() {};
}; };
typedef void (dummy::*safe_bool)(); typedef void (dummy::*safe_bool)();
@ -876,106 +767,24 @@ namespace boost {
{ {
if (!f.empty()) { if (!f.empty()) {
this->vtable = f.vtable; this->vtable = f.vtable;
if (this->has_trivial_copy_and_destroy()) f.vtable->manager(f.functor, this->functor,
this->functor = f.functor; boost::detail::function::clone_functor_tag);
else
get_vtable()->base.manager(f.functor, this->functor,
boost::detail::function::clone_functor_tag);
} }
} }
template<typename Functor> template<typename Functor>
void assign_to(Functor f) void assign_to(Functor f)
{ {
using detail::function::vtable_base; static vtable_type stored_vtable(f);
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
typedef typename detail::function::get_function_tag<Functor>::type tag; else vtable = 0;
typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker::
template apply<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS>
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
// Note: it is extremely important that this initialization use
// static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else
vtable = 0;
} }
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
void assign_to_a(Functor f,Allocator a) void assign_to_a(Functor f,Allocator a)
{ {
using detail::function::vtable_base; static vtable_type stored_vtable(f,a);
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
typedef typename detail::function::get_function_tag<Functor>::type tag; else vtable = 0;
typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator>
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
// Note: it is extremely important that this initialization use
// static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else
vtable = 0;
}
// Moves the value from the specified argument to *this. If the argument
// has its function object allocated on the heap, move_assign will pass
// its buffer to *this, and set the argument's buffer pointer to NULL.
void move_assign(BOOST_FUNCTION_FUNCTION& f)
{
if (&f == this)
return;
BOOST_TRY {
if (!f.empty()) {
this->vtable = f.vtable;
if (this->has_trivial_copy_and_destroy())
this->functor = f.functor;
else
get_vtable()->base.manager(f.functor, this->functor,
boost::detail::function::move_functor_tag);
f.vtable = 0;
} else {
clear();
}
} BOOST_CATCH (...) {
vtable = 0;
BOOST_RETHROW;
}
BOOST_CATCH_END
} }
}; };
@ -992,6 +801,21 @@ namespace boost {
f1.swap(f2); f1.swap(f2);
} }
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
typename BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
::operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#endif
// Poison comparisons between boost::function objects of the same type. // Poison comparisons between boost::function objects of the same type.
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
void operator==(const BOOST_FUNCTION_FUNCTION< void operator==(const BOOST_FUNCTION_FUNCTION<
@ -1114,13 +938,10 @@ public:
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_MEMBER_INVOKER
#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS #undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_TEMPLATE_ARGS
#undef BOOST_FUNCTION_PARMS #undef BOOST_FUNCTION_PARMS

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

@ -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)
; ;
@ -59,9 +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 : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ]
; ;
} }

View File

@ -128,10 +128,6 @@ test_main(int, char*[])
BOOST_CHECK(dealloc_count == 0); BOOST_CHECK(dealloc_count == 0);
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;
@ -698,7 +674,6 @@ 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();

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,28 +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 X { struct X {
int foo(int); int foo(int);
std::ostream& foo2(std::ostream&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
std::ostream& X::foo2(std::ostream& x) const { return x; }
int main() int main()
{ {
boost::function<int (X*, int)> f; boost::function<int (X*, int)> f;
boost::function<std::ostream& (X*, std::ostream&)> f2;
f = &X::foo; f = &X::foo;
f2 = &X::foo2;
X x;
f(&x, 5);
X x; return 0;
BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout);
return ::boost::report_errors();
} }

View File

@ -10,28 +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 X { struct X {
int foo(int); int foo(int);
std::ostream& foo2(std::ostream&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
std::ostream& X::foo2(std::ostream& x) const { return x; }
int main() int main()
{ {
boost::function2<int, X*, int> f; boost::function2<int, X*, int> f;
boost::function2<std::ostream&, X*, std::ostream&> f2;
f = &X::foo; f = &X::foo;
f2 = &X::foo2;
X x;
f(&x, 5);
X x; return 0;
BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout);
return ::boost::report_errors();
} }

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;
}