Compare commits

..

1 Commits

Author SHA1 Message Date
a0f7e705f9 Branch for 2nd try at V2 removal
[SVN r77497]
2012-03-23 12:04:44 +00:00
12 changed files with 262 additions and 568 deletions

View File

@ -3,7 +3,7 @@
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at # (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
project function/doc ; project boost/doc ;
import boostbook : boostbook ; import boostbook : boostbook ;
boostbook function-doc boostbook function-doc

View File

@ -13,15 +13,6 @@
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para><bold>Version 1.52.0</bold>: </para>
<itemizedlist spacing="compact">
<listitem><para>Move constructors and move assignment
operators added (only for compilers with C++11 rvalue
references support). Original patch
contributed by Antony Polukhin.</para></listitem>
</itemizedlist>
</listitem>
<listitem><para><bold>Version 1.37.0</bold>: </para> <listitem><para><bold>Version 1.37.0</bold>: </para>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
<listitem><para>Improved the performance of Boost.Function's <listitem><para>Improved the performance of Boost.Function's

View File

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

View File

@ -16,15 +16,16 @@
#include <memory> #include <memory>
#include <new> #include <new>
#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/integer.hpp>
#include <boost/type_index.hpp>
#include <boost/type_traits/has_trivial_copy.hpp> #include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_const.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/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>
@ -43,16 +44,47 @@
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif #endif
#if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
#ifdef BOOST_NO_STD_TYPEINFO
// Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS
#else
# define BOOST_FUNCTION_STD_NS std
#endif
// Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==.
#if defined( BOOST_NO_TYPEID )
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#elif (defined(__GNUC__) && __GNUC__ >= 3) \
|| defined(_AIX) \
|| ( defined(__sgi) && defined(__host_mips))
# include <cstring>
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
(std::strcmp((X).name(),(Y).name()) == 0)
# else
# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
#endif
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
#else #else
# define BOOST_FUNCTION_TARGET_FIX(x) # define BOOST_FUNCTION_TARGET_FIX(x)
#endif // __ICL etc #endif // not MSVC
#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
typename ::boost::enable_if_c< \ typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
!(::boost::is_integral<Functor>::value), \ (::boost::is_integral<Functor>::value)>::value), \
Type>::type Type>::type
#else
// BCC doesn't recognize this depends on a template argument and complains
// about the use of 'typename'
# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
::boost::enable_if_c<(::boost::type_traits::ice_not< \
(::boost::is_integral<Functor>::value)>::value), \
Type>::type
#endif
namespace boost { namespace boost {
namespace detail { namespace detail {
@ -65,16 +97,15 @@ namespace boost {
* object pointers, and a structure that resembles a bound * object pointers, and a structure that resembles a bound
* member function pointer. * member function pointer.
*/ */
union function_buffer_members union function_buffer
{ {
// For pointers to function objects // For pointers to function objects
typedef void* obj_ptr_t; mutable void* obj_ptr;
mutable obj_ptr_t obj_ptr;
// For pointers to std::type_info objects // For pointers to std::type_info objects
struct type_t { struct type_t {
// (get_functor_type_tag, check_functor_type_tag). // (get_functor_type_tag, check_functor_type_tag).
const boost::typeindex::type_info* type; const detail::sp_typeinfo* type;
// Whether the type is const-qualified. // Whether the type is const-qualified.
bool const_qualified; bool const_qualified;
@ -83,8 +114,7 @@ namespace boost {
} type; } type;
// For function pointers of all kinds // For function pointers of all kinds
typedef void (*func_ptr_t)(); mutable void (*func_ptr)();
mutable func_ptr_t func_ptr;
// For bound member pointers // For bound member pointers
struct bound_memfunc_ptr_t { struct bound_memfunc_ptr_t {
@ -99,15 +129,9 @@ namespace boost {
bool is_const_qualified; bool is_const_qualified;
bool is_volatile_qualified; bool is_volatile_qualified;
} obj_ref; } obj_ref;
};
union function_buffer
{
// Type-specific union members
mutable function_buffer_members members;
// To relax aliasing constraints // To relax aliasing constraints
mutable char data[sizeof(function_buffer_members)]; mutable char data;
}; };
/** /**
@ -179,37 +203,40 @@ namespace boost {
{ {
switch (op) { switch (op) {
case clone_functor_tag: case clone_functor_tag:
out_buffer.members.obj_ref = in_buffer.members.obj_ref; out_buffer.obj_ref = in_buffer.obj_ref;
return; return;
case move_functor_tag: case move_functor_tag:
out_buffer.members.obj_ref = in_buffer.members.obj_ref; out_buffer.obj_ref = in_buffer.obj_ref;
in_buffer.members.obj_ref.obj_ptr = 0; in_buffer.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.members.obj_ref.obj_ptr = 0; out_buffer.obj_ref.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
// Check whether we have the same type. We can add // Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away. // cv-qualifiers, but we can't take them away.
if (*out_buffer.members.type.type == boost::typeindex::type_id<F>() if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))
&& (!in_buffer.members.obj_ref.is_const_qualified && (!in_buffer.obj_ref.is_const_qualified
|| out_buffer.members.type.const_qualified) || out_buffer.type.const_qualified)
&& (!in_buffer.members.obj_ref.is_volatile_qualified && (!in_buffer.obj_ref.is_volatile_qualified
|| out_buffer.members.type.volatile_qualified)) || out_buffer.type.volatile_qualified))
out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr; out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(F);
out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified; out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified; out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -260,21 +287,23 @@ namespace boost {
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.members.func_ptr = in_buffer.members.func_ptr; out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) { else if (op == move_functor_tag) {
out_buffer.members.func_ptr = in_buffer.members.func_ptr; out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.members.func_ptr = 0; in_buffer.func_ptr = 0;
} else if (op == destroy_functor_tag) } else if (op == destroy_functor_tag)
out_buffer.members.func_ptr = 0; out_buffer.func_ptr = 0;
else if (op == check_functor_type_tag) { else if (op == check_functor_type_tag) {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const detail::sp_typeinfo& check_type
out_buffer.members.obj_ptr = &in_buffer.members.func_ptr; = *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
} }
} }
@ -285,28 +314,30 @@ namespace boost {
{ {
if (op == clone_functor_tag || op == move_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 (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor); new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);
if (op == move_functor_tag) { if (op == move_functor_tag) {
functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data); functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); 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); functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const detail::sp_typeinfo& check_type
out_buffer.members.obj_ptr = in_buffer.data; = *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = &in_buffer.data;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
} }
} }
}; };
@ -345,27 +376,29 @@ namespace boost {
// jewillco: Changing this to static_cast because GCC 2.95.3 is // jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete. // obsolete.
const functor_type* f = const functor_type* f =
static_cast<const functor_type*>(in_buffer.members.obj_ptr); static_cast<const functor_type*>(in_buffer.obj_ptr);
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
out_buffer.members.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.members.obj_ptr = 0; 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.members.obj_ptr); static_cast<functor_type*>(out_buffer.obj_ptr);
delete f; delete f;
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const detail::sp_typeinfo& check_type
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; = *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
} }
} }
@ -398,9 +431,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.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
return; return;
default: default:
@ -447,34 +480,36 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
const functor_wrapper_type* f = const functor_wrapper_type* f =
static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr); static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f); wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type // Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.members.obj_ptr = new_f; out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.members.obj_ptr = 0; 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 =
static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr); static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>()) const detail::sp_typeinfo& check_type
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr; = *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else else
out_buffer.members.obj_ptr = 0; out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
} }
} }
@ -499,9 +534,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.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
out_buffer.members.type.const_qualified = false; out_buffer.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false; out_buffer.type.volatile_qualified = false;
return; return;
default: default:
@ -600,15 +635,15 @@ public:
/** Determine if the function is empty (i.e., has no target). */ /** Determine if the function is empty (i.e., has no target). */
bool empty() const { return !vtable; } bool empty() const { return !vtable; }
/** Retrieve the type of the stored function object, or type_id<void>() /** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void)
if this is empty. */ if this is empty. */
const boost::typeindex::type_info& target_type() const const detail::sp_typeinfo& target_type() const
{ {
if (!vtable) return boost::typeindex::type_id<void>().type_info(); if (!vtable) return BOOST_SP_TYPEID(void);
detail::function::function_buffer type; detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.members.type.type; return *type.type.type;
} }
template<typename Functor> template<typename Functor>
@ -617,34 +652,42 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.type.type = &BOOST_SP_TYPEID(Functor);
type_result.members.type.const_qualified = is_const<Functor>::value; type_result.type.const_qualified = is_const<Functor>::value;
type_result.members.type.volatile_qualified = is_volatile<Functor>::value; type_result.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.members.obj_ptr); return static_cast<Functor*>(type_result.obj_ptr);
} }
template<typename Functor> template<typename Functor>
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
const Functor* target( Functor * = 0 ) const
#else
const Functor* target() const const Functor* target() const
#endif
{ {
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.type.type = &BOOST_SP_TYPEID(Functor);
type_result.members.type.const_qualified = true; type_result.type.const_qualified = true;
type_result.members.type.volatile_qualified = is_volatile<Functor>::value; type_result.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
return static_cast<const Functor*>(type_result.members.obj_ptr); return static_cast<const Functor*>(type_result.obj_ptr);
} }
template<typename F> template<typename F>
bool contains(const F& f) const bool contains(const F& f) const
{ {
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
if (const F* fp = this->target( (F*)0 ))
#else
if (const F* fp = this->template target<F>()) if (const F* fp = this->template target<F>())
#endif
{ {
return function_equal(*fp, f); return function_equal(*fp, f);
} else { } else {
@ -858,6 +901,7 @@ namespace detail {
} // end namespace boost } // end namespace boost
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( pop ) # pragma warning( pop )

View File

@ -19,7 +19,8 @@ namespace boost { namespace python { namespace objects {
}}} }}}
#endif #endif
#if defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
#endif #endif

View File

@ -26,13 +26,7 @@
#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
#else
# include <boost/move/utility_core.hpp>
# define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I))
# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
#endif
#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
@ -97,7 +91,7 @@ namespace boost {
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
return f(BOOST_FUNCTION_ARGS); return f(BOOST_FUNCTION_ARGS);
} }
}; };
@ -114,7 +108,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
} }
}; };
@ -132,9 +126,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -153,9 +147,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -172,7 +166,7 @@ namespace boost {
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -190,7 +184,7 @@ namespace boost {
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -209,7 +203,7 @@ namespace boost {
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(function_obj_ptr.data); reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -227,7 +221,7 @@ namespace boost {
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(function_obj_ptr.data); reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -520,7 +514,7 @@ namespace boost {
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.members.func_ptr = reinterpret_cast<void (*)()>(f); functor.func_ptr = reinterpret_cast<void (*)()>(f);
return true; return true;
} else { } else {
return false; return false;
@ -569,7 +563,7 @@ namespace boost {
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
{ {
new (reinterpret_cast<void*>(functor.data)) FunctionObj(f); new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
@ -583,7 +577,7 @@ namespace boost {
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
{ {
functor.members.obj_ptr = new FunctionObj(f); functor.obj_ptr = new FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
@ -597,7 +591,7 @@ namespace boost {
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
functor.members.obj_ptr = new_f; functor.obj_ptr = new_f;
} }
template<typename FunctionObj> template<typename FunctionObj>
@ -631,9 +625,9 @@ namespace boost {
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) const
{ {
functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer()); functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value; functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true; return true;
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
@ -683,7 +677,7 @@ namespace boost {
vtable_type* get_vtable() const { vtable_type* get_vtable() const {
return reinterpret_cast<vtable_type*>( return reinterpret_cast<vtable_type*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01)); reinterpret_cast<std::size_t>(vtable) & ~static_cast<size_t>(0x01));
} }
struct clear_type {}; struct clear_type {};
@ -717,8 +711,9 @@ namespace boost {
template<typename Functor> template<typename Functor>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename boost::enable_if_c< ,typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif // BOOST_NO_SFINAE #endif // BOOST_NO_SFINAE
) : ) :
@ -729,8 +724,9 @@ namespace boost {
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename boost::enable_if_c< ,typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif // BOOST_NO_SFINAE #endif // BOOST_NO_SFINAE
) : ) :
@ -753,13 +749,6 @@ namespace boost {
this->assign_to_own(f); this->assign_to_own(f);
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
{
this->move_assign(f);
}
#endif
~BOOST_FUNCTION_FUNCTION() { clear(); } ~BOOST_FUNCTION_FUNCTION() { clear(); }
result_type operator()(BOOST_FUNCTION_PARMS) const result_type operator()(BOOST_FUNCTION_PARMS) const
@ -778,8 +767,9 @@ namespace boost {
// construct. // construct.
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename boost::enable_if_c< typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
BOOST_FUNCTION_FUNCTION&>::type BOOST_FUNCTION_FUNCTION&>::type
#else #else
BOOST_FUNCTION_FUNCTION& BOOST_FUNCTION_FUNCTION&
@ -841,25 +831,6 @@ namespace boost {
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
{
if (&f == this)
return *this;
this->clear();
BOOST_TRY {
this->move_assign(f);
} BOOST_CATCH (...) {
vtable = 0;
BOOST_RETHROW;
}
BOOST_CATCH_END
return *this;
}
#endif
void swap(BOOST_FUNCTION_FUNCTION& other) void swap(BOOST_FUNCTION_FUNCTION& other)
{ {
if (&other == this) if (&other == this)
@ -916,10 +887,10 @@ namespace boost {
template<typename Functor> template<typename Functor>
void assign_to(Functor f) void assign_to(Functor f)
{ {
using boost::detail::function::vtable_base; using detail::function::vtable_base;
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply<Functor, R BOOST_FUNCTION_COMMA template apply<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS> BOOST_FUNCTION_TEMPLATE_ARGS>
@ -937,12 +908,11 @@ namespace boost {
if (stored_vtable.assign_to(f, functor)) { if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value && if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value && boost::has_trivial_destructor<Functor>::value &&
boost::detail::function::function_allows_small_object_optimization<Functor>::value) detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
@ -950,10 +920,10 @@ namespace boost {
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 boost::detail::function::vtable_base; using detail::function::vtable_base;
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS, BOOST_FUNCTION_TEMPLATE_ARGS,
@ -972,12 +942,11 @@ namespace boost {
if (stored_vtable.assign_to_a(f, functor, a)) { if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value && if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value && boost::has_trivial_destructor<Functor>::value &&
boost::detail::function::function_allows_small_object_optimization<Functor>::value) detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
@ -1064,8 +1033,9 @@ public:
template<typename Functor> template<typename Functor>
function(Functor f function(Functor f
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename boost::enable_if_c< ,typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif #endif
) : ) :
@ -1075,8 +1045,9 @@ public:
template<typename Functor,typename Allocator> template<typename Functor,typename Allocator>
function(Functor f, Allocator a function(Functor f, Allocator a
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
,typename boost::enable_if_c< ,typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
int>::type = 0 int>::type = 0
#endif #endif
) : ) :
@ -1092,30 +1063,17 @@ public:
function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move constructors
function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
#endif
self_type& operator=(const self_type& f) self_type& operator=(const self_type& f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(self_type&& f)
{
self_type(static_cast<self_type&&>(f)).swap(*this);
return *this;
}
#endif
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
typename boost::enable_if_c< typename enable_if_c<
!(is_integral<Functor>::value), (boost::type_traits::ice_not<
(is_integral<Functor>::value)>::value),
self_type&>::type self_type&>::type
#else #else
self_type& self_type&
@ -1139,14 +1097,6 @@ public:
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(base_type&& f)
{
self_type(static_cast<base_type&&>(f)).swap(*this);
return *this;
}
#endif
}; };
#undef BOOST_FUNCTION_PARTIAL_SPEC #undef BOOST_FUNCTION_PARTIAL_SPEC
@ -1175,9 +1125,6 @@ public:
#undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_TEMPLATE_ARGS
#undef BOOST_FUNCTION_PARMS #undef BOOST_FUNCTION_PARMS
#undef BOOST_FUNCTION_PARM #undef BOOST_FUNCTION_PARM
#ifdef BOOST_FUNCTION_ARG
# undef BOOST_FUNCTION_ARG
#endif
#undef BOOST_FUNCTION_ARGS #undef BOOST_FUNCTION_ARGS
#undef BOOST_FUNCTION_ARG_TYPE #undef BOOST_FUNCTION_ARG_TYPE
#undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_ARG_TYPES

View File

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

View File

@ -21,8 +21,6 @@ import testing ;
: :
[ run libs/function/test/function_test.cpp : : : : lib_function_test ] [ run libs/function/test/function_test.cpp : : : : lib_function_test ]
[ run libs/function/test/function_test.cpp : : : <rtti>off : lib_function_test_no_rtti ]
[ run libs/function/test/function_n_test.cpp : : : : ] [ run libs/function/test/function_n_test.cpp : : : : ]
[ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ] [ run libs/function/test/allocator_test.cpp ../../../libs/test/build//boost_test_exec_monitor : : : : ]
@ -63,8 +61,6 @@ import testing ;
[ run libs/function/test/nothrow_swap.cpp : : : : ] [ run libs/function/test/nothrow_swap.cpp : : : : ]
[ run libs/function/test/rvalues_test.cpp : : : : ]
[ compile libs/function/test/function_typeof_test.cpp ] [ compile libs/function/test/function_typeof_test.cpp ]
; ;
} }

View File

@ -690,95 +690,6 @@ static void test_call()
test_call_cref(std::plus<int>()); test_call_cref(std::plus<int>());
} }
struct big_aggregating_structure {
int disable_small_objects_optimizations[32];
big_aggregating_structure()
{
++ global_int;
}
big_aggregating_structure(const big_aggregating_structure&)
{
++ global_int;
}
~big_aggregating_structure()
{
-- global_int;
}
void operator()()
{
++ global_int;
}
void operator()(int)
{
++ global_int;
}
};
template <class FunctionT>
static void test_move_semantics()
{
typedef FunctionT f1_type;
big_aggregating_structure obj;
f1_type f1 = obj;
global_int = 0;
f1();
BOOST_CHECK(!f1.empty());
BOOST_CHECK(global_int == 1);
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Testing rvalue constructors
f1_type f2(static_cast<f1_type&&>(f1));
BOOST_CHECK(f1.empty());
BOOST_CHECK(!f2.empty());
BOOST_CHECK(global_int == 1);
f2();
BOOST_CHECK(global_int == 2);
f1_type f3(static_cast<f1_type&&>(f2));
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(!f3.empty());
BOOST_CHECK(global_int == 2);
f3();
BOOST_CHECK(global_int == 3);
// Testing move assignment
f1_type f4;
BOOST_CHECK(f4.empty());
f4 = static_cast<f1_type&&>(f3);
BOOST_CHECK(f1.empty());
BOOST_CHECK(f2.empty());
BOOST_CHECK(f3.empty());
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 3);
f4();
BOOST_CHECK(global_int == 4);
// Testing self move assignment
f4 = static_cast<f1_type&&>(f4);
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
// Testing, that no memory leaked when assigning to nonempty function
f4 = obj;
BOOST_CHECK(!f4.empty());
BOOST_CHECK(global_int == 4);
f1_type f5 = obj;
BOOST_CHECK(global_int == 5);
f4 = static_cast<f1_type&&>(f5);
BOOST_CHECK(global_int == 4);
#endif
}
int test_main(int, char* []) int test_main(int, char* [])
{ {
test_zero_args(); test_zero_args();
@ -791,8 +702,6 @@ int test_main(int, char* [])
test_exception(); test_exception();
test_implicit(); test_implicit();
test_call(); test_call();
test_move_semantics<function<void()> >();
test_move_semantics<boost::function0<void> >();
return 0; return 0;
} }

View File

@ -14,32 +14,24 @@
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
Y& foo2(Y&) const; std::ostream& foo2(std::ostream&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
Y& X::foo2(Y& x) const { 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<Y& (X*, Y&)> f2; boost::function<std::ostream& (X*, std::ostream&)> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2; f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(y1)) == y1); BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout);
return ::boost::report_errors(); return ::boost::report_errors();
} }

View File

@ -14,32 +14,24 @@
#include <iostream> #include <iostream>
#include <functional> #include <functional>
struct Y {
Y(int y = 0) : y_(y) {}
bool operator==(const Y& rhs) { return y_ == rhs.y_; }
private:
int y_;
};
struct X { struct X {
int foo(int); int foo(int);
Y& foo2(Y&) const; std::ostream& foo2(std::ostream&) const;
}; };
int X::foo(int x) { return -x; } int X::foo(int x) { return -x; }
Y& X::foo2(Y& x) const { 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<Y&, X*, Y&> f2; boost::function2<std::ostream&, X*, std::ostream&> f2;
Y y1;
f = &X::foo; f = &X::foo;
f2 = &X::foo2; f2 = &X::foo2;
X x; X x;
BOOST_TEST(f(&x, 5) == -5); BOOST_TEST(f(&x, 5) == -5);
BOOST_TEST(f2(&x, boost::ref(y1)) == y1); BOOST_TEST(f2(&x, boost::ref(std::cout)) == std::cout);
return ::boost::report_errors(); return ::boost::report_errors();
} }

View File

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