Compare commits

..

4 Commits

13 changed files with 202 additions and 741 deletions

View File

@ -1,22 +0,0 @@
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
function.hpp
function
)
# Add a library target to the build system
boost_library_project(
function
# SRCDIRS
TESTDIRS test
HEADERS ${lib_headers}
DOCDIRS doc
# DESCRIPTION
MODULARIZED
# AUTHORS
# MAINTAINERS
)

View File

@ -1,2 +0,0 @@
boost_add_documentation(function.xml
faq.xml history.xml misc.xml reference.xml tests.xml tutorial.xml)

View File

@ -13,26 +13,6 @@
<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>
<itemizedlist spacing="compact">
<listitem><para>Boost.Function now implements allocator support

View File

@ -18,11 +18,8 @@
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_const.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/ice.hpp>
#include <boost/ref.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/workaround.hpp>
@ -33,7 +30,6 @@
# include "boost/mpl/bool.hpp"
#endif
#include <boost/function_equal.hpp>
#include <boost/function/function_fwd.hpp>
#if defined(BOOST_MSVC)
# pragma warning( push )
@ -42,7 +38,7 @@
#endif
// 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
# define BOOST_FUNCTION_STD_NS
#else
@ -67,7 +63,22 @@
# define BOOST_FUNCTION_TARGET_FIX(x)
#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) \
typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
@ -81,6 +92,22 @@
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 detail {
namespace function {
@ -95,18 +122,11 @@ namespace boost {
union function_buffer
{
// For pointers to function objects
mutable void* obj_ptr;
void* obj_ptr;
// For pointers to std::type_info objects
struct type_t {
// (get_functor_type_tag, check_functor_type_tag).
const BOOST_FUNCTION_STD_NS::type_info* type;
// Whether the type is const-qualified.
bool const_qualified;
// Whether the type is volatile-qualified.
bool volatile_qualified;
} type;
const void* const_obj_ptr;
// For function pointers of all kinds
mutable void (*func_ptr)();
@ -117,14 +137,6 @@ namespace boost {
void* obj_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
mutable char data;
};
@ -156,7 +168,6 @@ namespace boost {
// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type {
clone_functor_tag,
move_functor_tag,
destroy_functor_tag,
check_functor_type_tag,
get_functor_type_tag
@ -193,45 +204,34 @@ namespace boost {
struct reference_manager
{
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)
{
switch (op) {
case clone_functor_tag:
out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
return;
case move_functor_tag:
out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
in_buffer.obj_ref.obj_ptr = 0;
out_buffer.obj_ptr = in_buffer.obj_ptr;
return;
case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0;
out_buffer.obj_ptr = 0;
return;
case check_functor_type_tag:
{
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
// Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away.
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
&& (!in_buffer.obj_ref.is_const_qualified
|| 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;
// DPG TBD: Since we're only storing a pointer, it's
// possible that the user could ask for a base class or
// derived class. Is that okay?
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
out_buffer.obj_ptr = 0;
}
return;
case get_functor_type_tag:
out_buffer.type.type = &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;
out_buffer.const_obj_ptr = &typeid(F);
return;
}
}
@ -277,22 +277,15 @@ namespace boost {
{
if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.func_ptr = 0;
} else if (op == destroy_functor_tag)
else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*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.func_ptr;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
@ -301,28 +294,20 @@ namespace boost {
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == clone_functor_tag || op == move_functor_tag) {
if (op == clone_functor_tag) {
const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data);
new ((void*)&out_buffer.data) functor_type(*in_functor);
if (op == move_functor_tag) {
reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();
}
} else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*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.data;
else
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
};
@ -362,26 +347,19 @@ namespace boost {
(const functor_type*)(in_buffer.obj_ptr);
functor_type* new_f = new functor_type(*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) {
/* Cast from the void pointer to the functor pointer type */
functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr);
delete f;
out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*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
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
@ -396,14 +374,6 @@ namespace boost {
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:
/* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */
@ -414,9 +384,7 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.type.type = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.const_obj_ptr = &typeid(functor_type);
return;
default:
@ -471,9 +439,6 @@ namespace boost {
// Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
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) {
/* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim =
@ -482,17 +447,13 @@ namespace boost {
wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
= *out_buffer.type.type;
} else /* op == check_functor_type_tag */ {
const BOOST_FUNCTION_STD_NS::type_info& check_type =
*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
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &typeid(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
@ -517,9 +478,7 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.type.type = &typeid(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.const_obj_ptr = &typeid(functor_type);
return;
default:
@ -597,6 +556,7 @@ namespace boost {
*/
struct vtable_base
{
vtable_base() : manager(0) { }
void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer,
functor_manager_operation_type op);
@ -626,7 +586,7 @@ public:
detail::function::function_buffer type;
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>
@ -635,9 +595,7 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &typeid(Functor);
type_result.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
type_result.const_obj_ptr = &typeid(Functor);
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr);
@ -653,9 +611,7 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &typeid(Functor);
type_result.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
type_result.const_obj_ptr = &typeid(Functor);
vtable->manager(functor, type_result,
detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we

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) \
|| !(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

@ -53,20 +53,12 @@
BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
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 \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
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)
#ifndef BOOST_NO_VOID_RETURNS
@ -188,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<
typename FunctionPtr,
typename R BOOST_FUNCTION_COMMA
@ -289,190 +243,11 @@ namespace boost {
>::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
* 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.
* vtable for a specific boost::function instance.
*/
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
typedef R result_type;
@ -484,6 +259,17 @@ namespace boost {
BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS);
template<typename F>
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)
{
@ -499,12 +285,52 @@ namespace boost {
void clear(function_buffer& functor)
{
if (base.manager)
base.manager(functor, functor, destroy_functor_tag);
if (manager)
manager(functor, functor, destroy_functor_tag);
}
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
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>
bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
@ -528,6 +354,23 @@ namespace boost {
// Member pointers
#if BOOST_FUNCTION_NUM_ARGS > 0
template<typename MemberPtr>
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)
{
@ -557,6 +400,33 @@ namespace boost {
#endif // BOOST_FUNCTION_NUM_ARGS > 0
// 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
template<typename FunctionObj>
void
@ -619,15 +489,38 @@ namespace boost {
}
// 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>
bool
assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag)
{
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
functor.obj_ref.obj_ptr = (void *)f.get_pointer();
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
// DPG TBD: We might need to detect constness of
// FunctionObj to assign into obj_ptr or const_obj_ptr to
// 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;
@ -642,7 +535,6 @@ namespace boost {
}
public:
vtable_base base;
invoker_type invoker;
};
} // end namespace function
@ -837,17 +729,16 @@ namespace boost {
if (&other == this)
return;
BOOST_FUNCTION_FUNCTION tmp;
tmp.move_assign(*this);
this->move_assign(other);
other.move_assign(tmp);
BOOST_FUNCTION_FUNCTION tmp = *this;
*this = other;
other = tmp;
}
// Clear out a target, if there is one
void clear()
{
if (vtable) {
reinterpret_cast<vtable_type*>(vtable)->clear(this->functor);
static_cast<vtable_type*>(vtable)->clear(this->functor);
vtable = 0;
}
}
@ -884,82 +775,17 @@ namespace boost {
template<typename Functor>
void assign_to(Functor f)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag<Functor>::type tag;
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 vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base;
static vtable_type stored_vtable(f);
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
else vtable = 0;
}
template<typename Functor,typename Allocator>
void assign_to_a(Functor f,Allocator a)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag<Functor>::type tag;
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 vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable.base;
static vtable_type stored_vtable(f,a);
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
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;
#if !defined(BOOST_NO_EXCEPTIONS)
try {
#endif
if (!f.empty()) {
this->vtable = f.vtable;
f.vtable->manager(f.functor, this->functor,
boost::detail::function::move_functor_tag);
f.vtable = 0;
#if !defined(BOOST_NO_EXCEPTIONS)
} else {
clear();
}
} catch (...) {
vtable = 0;
throw;
}
#endif
}
};
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
@ -985,7 +811,7 @@ namespace boost {
if (this->empty())
boost::throw_exception(bad_function_call());
return reinterpret_cast<const vtable_type*>(vtable)->invoker
return static_cast<vtable_type*>(vtable)->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#endif
@ -1112,13 +938,10 @@ public:
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_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_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
#undef BOOST_FUNCTION_GET_INVOKER
#undef BOOST_FUNCTION_TEMPLATE_PARMS
#undef BOOST_FUNCTION_TEMPLATE_ARGS
#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

@ -1,20 +0,0 @@
boost_test_run(lib_function_test function_test.cpp)
boost_test_run(function_n_test)
boost_test_run(allocator_test)
boost_test_run(stateless_test)
boost_test_run(lambda_test)
boost_test_compile_fail(function_test_fail1)
boost_test_compile_fail(function_test_fail2)
boost_test_compile(function_30)
boost_test_run(function_arith_cxx98)
boost_test_run(function_arith_portable)
boost_test_run(sum_avg_cxx98)
boost_test_run(sum_avg_portable)
boost_test_run(mem_fun_cxx98)
boost_test_run(mem_fun_portable)
boost_test_run(std_bind_cxx98)
boost_test_run(std_bind_portable)
boost_test_run(function_ref_cxx98)
boost_test_run(function_ref_portable)
boost_test_run(contains_test)
boost_test_run(contains2_test)

View File

@ -58,9 +58,6 @@ import testing ;
[ run libs/function/test/contains2_test.cpp : : : : ]
[ run libs/function/test/nothrow_swap.cpp : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ]
;
}

View File

@ -88,15 +88,6 @@ static void target_test()
BOOST_CHECK(!f.target<int (*)()>());
BOOST_CHECK(f.target<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()

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* [])
{
test_zero_args();
@ -692,6 +644,5 @@ int test_main(int, char* [])
test_emptiness();
test_member_functions();
test_ref();
test_construct_destroy_count();
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

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