mirror of
https://github.com/boostorg/function.git
synced 2025-06-26 12:31:33 +02:00
Compare commits
8 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
98a207958d | |||
75890fea53 | |||
da259e8dce | |||
2fe4cc253f | |||
f379ef8532 | |||
ea18f5777b | |||
d5a86a2d52 | |||
e3dfa7268a |
@ -13,6 +13,26 @@
|
|||||||
|
|
||||||
<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 <boost/function/function_typeof.hpp> that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Added a new header <boost/function/function_fwd.hpp> 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
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.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>
|
||||||
@ -30,6 +33,7 @@
|
|||||||
# 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 )
|
||||||
@ -63,22 +67,7 @@
|
|||||||
# define BOOST_FUNCTION_TARGET_FIX(x)
|
# define BOOST_FUNCTION_TARGET_FIX(x)
|
||||||
#endif // not MSVC
|
#endif // not MSVC
|
||||||
|
|
||||||
#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
|
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
|
||||||
// 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), \
|
||||||
@ -92,22 +81,6 @@ namespace boost { namespace python { namespace objects {
|
|||||||
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 {
|
||||||
@ -122,11 +95,18 @@ namespace boost {
|
|||||||
union function_buffer
|
union function_buffer
|
||||||
{
|
{
|
||||||
// For pointers to function objects
|
// For pointers to function objects
|
||||||
void* obj_ptr;
|
mutable 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 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;
|
||||||
|
|
||||||
// For function pointers of all kinds
|
// For function pointers of all kinds
|
||||||
mutable void (*func_ptr)();
|
mutable void (*func_ptr)();
|
||||||
@ -137,6 +117,14 @@ 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;
|
||||||
};
|
};
|
||||||
@ -168,6 +156,7 @@ 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
|
||||||
@ -209,29 +198,40 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case clone_functor_tag:
|
case clone_functor_tag:
|
||||||
out_buffer.obj_ptr = in_buffer.obj_ptr;
|
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;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case destroy_functor_tag:
|
case destroy_functor_tag:
|
||||||
out_buffer.obj_ptr = 0;
|
out_buffer.obj_ref.obj_ptr = 0;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case check_functor_type_tag:
|
case check_functor_type_tag:
|
||||||
{
|
{
|
||||||
// DPG TBD: Since we're only storing a pointer, it's
|
const BOOST_FUNCTION_STD_NS::type_info& check_type
|
||||||
// possible that the user could ask for a base class or
|
= *out_buffer.type.type;
|
||||||
// derived class. Is that okay?
|
|
||||||
const BOOST_FUNCTION_STD_NS::type_info& check_type =
|
// Check whether we have the same type. We can add
|
||||||
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
|
// cv-qualifiers, but we can't take them away.
|
||||||
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
|
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
|
||||||
out_buffer.obj_ptr = in_buffer.obj_ptr;
|
&& (!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;
|
||||||
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.const_obj_ptr = &typeid(F);
|
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;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,15 +277,22 @@ 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 == destroy_functor_tag)
|
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)
|
||||||
out_buffer.func_ptr = 0;
|
out_buffer.func_ptr = 0;
|
||||||
else /* op == check_functor_type_tag */ {
|
else if (op == check_functor_type_tag) {
|
||||||
const BOOST_FUNCTION_STD_NS::type_info& check_type =
|
const BOOST_FUNCTION_STD_NS::type_info& check_type
|
||||||
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
|
= *out_buffer.type.type;
|
||||||
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, 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 = &typeid(Functor);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,20 +301,28 @@ 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) {
|
if (op == clone_functor_tag || op == move_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 ((void*)&out_buffer.data) functor_type(*in_functor);
|
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) {
|
} else if (op == destroy_functor_tag) {
|
||||||
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
|
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
|
||||||
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
|
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
|
||||||
} else /* op == check_functor_type_tag */ {
|
} else if (op == check_functor_type_tag) {
|
||||||
const BOOST_FUNCTION_STD_NS::type_info& check_type =
|
const BOOST_FUNCTION_STD_NS::type_info& check_type
|
||||||
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
|
= *out_buffer.type.type;
|
||||||
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
|
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, 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 = &typeid(Functor);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -347,19 +362,26 @@ namespace boost {
|
|||||||
(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 /* op == check_functor_type_tag */ {
|
} else if (op == check_functor_type_tag) {
|
||||||
const BOOST_FUNCTION_STD_NS::type_info& check_type =
|
const BOOST_FUNCTION_STD_NS::type_info& check_type
|
||||||
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
|
= *out_buffer.type.type;
|
||||||
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, 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 = &typeid(Functor);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +406,9 @@ 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.const_obj_ptr = &typeid(functor_type);
|
out_buffer.type.type = &typeid(functor_type);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -439,6 +463,9 @@ 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 =
|
||||||
@ -447,13 +474,17 @@ 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 /* op == check_functor_type_tag */ {
|
} else if (op == check_functor_type_tag) {
|
||||||
const BOOST_FUNCTION_STD_NS::type_info& check_type =
|
const BOOST_FUNCTION_STD_NS::type_info& check_type
|
||||||
*static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
|
= *out_buffer.type.type;
|
||||||
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, 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 = &typeid(Functor);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +509,9 @@ 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.const_obj_ptr = &typeid(functor_type);
|
out_buffer.type.type = &typeid(functor_type);
|
||||||
|
out_buffer.type.const_qualified = false;
|
||||||
|
out_buffer.type.volatile_qualified = false;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -586,7 +619,7 @@ public:
|
|||||||
|
|
||||||
detail::function::function_buffer type;
|
detail::function::function_buffer type;
|
||||||
vtable->manager(functor, type, detail::function::get_functor_type_tag);
|
vtable->manager(functor, type, detail::function::get_functor_type_tag);
|
||||||
return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
|
return *type.type.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
@ -595,7 +628,9 @@ public:
|
|||||||
if (!vtable) return 0;
|
if (!vtable) return 0;
|
||||||
|
|
||||||
detail::function::function_buffer type_result;
|
detail::function::function_buffer type_result;
|
||||||
type_result.const_obj_ptr = &typeid(Functor);
|
type_result.type.type = &typeid(Functor);
|
||||||
|
type_result.type.const_qualified = is_const<Functor>::value;
|
||||||
|
type_result.type.volatile_qualified = is_volatile<Functor>::value;
|
||||||
vtable->manager(functor, type_result,
|
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);
|
||||||
@ -611,7 +646,9 @@ public:
|
|||||||
if (!vtable) return 0;
|
if (!vtable) return 0;
|
||||||
|
|
||||||
detail::function::function_buffer type_result;
|
detail::function::function_buffer type_result;
|
||||||
type_result.const_obj_ptr = &typeid(Functor);
|
type_result.type.type = &typeid(Functor);
|
||||||
|
type_result.type.const_qualified = true;
|
||||||
|
type_result.type.volatile_qualified = is_volatile<Functor>::value;
|
||||||
vtable->manager(functor, type_result,
|
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
|
||||||
|
70
include/boost/function/function_fwd.hpp
Normal file
70
include/boost/function/function_fwd.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// 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
|
@ -516,11 +516,9 @@ namespace boost {
|
|||||||
function_buffer& functor, function_obj_ref_tag)
|
function_buffer& functor, function_obj_ref_tag)
|
||||||
{
|
{
|
||||||
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
||||||
// DPG TBD: We might need to detect constness of
|
functor.obj_ref.obj_ptr = (void *)f.get_pointer();
|
||||||
// FunctionObj to assign into obj_ptr or const_obj_ptr to
|
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
|
||||||
// be truly legit, but no platform in existence makes
|
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
|
||||||
// const void* different from void*.
|
|
||||||
functor.const_obj_ptr = f.get_pointer();
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -729,9 +727,10 @@ namespace boost {
|
|||||||
if (&other == this)
|
if (&other == this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
BOOST_FUNCTION_FUNCTION tmp = *this;
|
BOOST_FUNCTION_FUNCTION tmp;
|
||||||
*this = other;
|
tmp.move_assign(*this);
|
||||||
other = tmp;
|
this->move_assign(other);
|
||||||
|
other.move_assign(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear out a target, if there is one
|
// Clear out a target, if there is one
|
||||||
@ -786,6 +785,33 @@ namespace boost {
|
|||||||
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
|
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
|
||||||
else vtable = 0;
|
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>
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
|
||||||
|
45
include/boost/function/function_typeof.hpp
Normal file
45
include/boost/function/function_typeof.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// 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
|
@ -58,6 +58,9 @@ 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 ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,15 @@ 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()
|
||||||
|
@ -636,6 +636,54 @@ 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();
|
||||||
@ -644,5 +692,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
18
test/function_typeof_test.cpp
Normal file
18
test/function_typeof_test.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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));
|
||||||
|
}
|
60
test/nothrow_swap.cpp
Normal file
60
test/nothrow_swap.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
Reference in New Issue
Block a user