Compare commits

..

25 Commits

Author SHA1 Message Date
0a5d7d1356 v2, v3, integration branch
[SVN r62649]
2010-06-09 11:34:33 +00:00
6902f6f943 Applied patch from #4073; fixes #4073
[SVN r62623]
2010-06-09 00:51:41 +00:00
c4f1ce7cb1 Applied patch from #3912; fixes #3912
[SVN r62622]
2010-06-09 00:49:45 +00:00
820ad024fe Applied patch from #3618; fixes #3618
[SVN r62621]
2010-06-09 00:47:51 +00:00
2e19728cdb Removed all but one old-style cast, breaking GCC 2.95.3; fixes #3410
[SVN r62614]
2010-06-08 23:55:25 +00:00
de3b8e7451 Fixed tab and no-newline-at-end-of-file issues from inspection report
[SVN r61435]
2010-04-20 17:54:16 +00:00
22c6592a40 Fix function_base.hpp to not require typeid. Refs #3666. Requires [58127].
[SVN r58128]
2009-12-03 20:59:32 +00:00
a1f62de420 rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
81c7876588 Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
2020d39e2c Fix a typo.
[SVN r54909]
2009-07-12 15:53:54 +00:00
8b63c146ea Work around Visual C++ copy constructor bug. Fixes #2929.
Based on the patch by Steven Watanabe.

[SVN r54619]
2009-07-03 22:22:03 +00:00
ae534d7342 Fix Boost.Function unit tests for C++0x. Fixes #3012
Based on a patch from Richard Webb. Changed a bit so that it also
works for the Visual C++ 10 beta.

[SVN r54618]
2009-07-03 22:21:40 +00:00
e8247198fa Add 'and later versions' to support info for GCC and Visual C++. Fixes #2847.
I didn't explicitly specify the versions since no one's updating this
list and it's highly unlikely that a future version will break this. The
same could probably be done for the other compilers but I don't know
them very well so I'm leaving them alone.

[SVN r54617]
2009-07-03 22:20:52 +00:00
ff3244d562 When copying boost::ref, copy even when the referenced function is empty. Fixes #2642
Patch by Steven Watanabe

[SVN r54616]
2009-07-03 22:20:26 +00:00
68128bfffa Make Boost.Function compile with disabled exceptions.
Closes #2900. Patch from Gabi Davar.


[SVN r53722]
2009-06-07 15:44:50 +00:00
e10f4eaef9 Add missing #pragma warning(pop). Fixes #2767.
[SVN r53694]
2009-06-06 15:31:47 +00:00
a74e72cce9 Make Boost.Function compile under BOOST_NO_EXCEPTIONS.
Fixes #2499
Fixes #2494
Fixes #2469
Fixes #2466


[SVN r51745]
2009-03-13 05:49:02 +00:00
6f8ec5c8c5 Implement an optimization that David Abrahams and myself came up with,
where Boost.Function uses a bit in the vtable pointer to indicate when
the target function object has a trivial copy constructor, trivial
destructor, and fits within the small object buffer. In this case, we
just copy the bits of the function object rather than performing an
indirect call to the manager.

This results in a 60% speedup on a micro-benchmark that copies and
calls such function objects repeatedly.



[SVN r51743]
2009-03-13 05:23:53 +00:00
678fb133f0 Add PDF generation options to fix external links to point to the web site.
Added a few more Boostbook based libs that were missed first time around.
Fixed PDF naming issues.

[SVN r51284]
2009-02-17 10:05:58 +00:00
821e6d34dd Fix -Wundef warning and suspect usage of BOOST_STRICT_CONFIG.
[SVN r50064]
2008-12-02 10:10:46 +00:00
529dc74954 Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
e8504c1777 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
07800455a8 Both Sun and Pgi on Linux correctly put typeinfo into the std
namespace, but function_base keys off the
BOOST_NO_EXCEPTION_STD_NAMESPACE macro instead of the
BOOST_NO_STD_TYPEINFO macro.  The attached patch changes
function_base to use the typeinfo macro.  Because eVC 4.2 doesn't
put typeinfo into the std namespace, I need to define
BOOST_NO_STD_TYPEINFO only for this eVC version.



[SVN r49571]
2008-11-03 18:37:49 +00:00
f559986ae8 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
8ca7384121 Fix Boost.Function thread safety issue again
[SVN r49326]
2008-10-14 15:31:57 +00:00
10 changed files with 184 additions and 95 deletions

View File

@ -6,5 +6,10 @@
project boost/doc ;
import boostbook : boostbook ;
boostbook function-doc : function.xml ;
boostbook function-doc
:
function.xml
:
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;

View File

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

View File

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

View File

@ -15,9 +15,12 @@
#include <string>
#include <memory>
#include <new>
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/assert.hpp>
#include <boost/integer.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_volatile.hpp>
@ -42,7 +45,7 @@
#endif
// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE
#ifdef BOOST_NO_STD_TYPEINFO
// Embedded VC++ does not have type_info in namespace std
# define BOOST_FUNCTION_STD_NS
#else
@ -51,7 +54,9 @@
// Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
#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>
@ -100,7 +105,7 @@ namespace boost {
// 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;
const detail::sp_typeinfo* type;
// Whether the type is const-qualified.
bool const_qualified;
@ -212,12 +217,12 @@ namespace boost {
case check_functor_type_tag:
{
const BOOST_FUNCTION_STD_NS::type_info& check_type
const detail::sp_typeinfo& 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))
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))
&& (!in_buffer.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified
@ -229,7 +234,7 @@ namespace boost {
return;
case get_functor_type_tag:
out_buffer.type.type = &typeid(F);
out_buffer.type.type = &BOOST_SP_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;
@ -259,6 +264,12 @@ namespace boost {
A(a)
{
}
functor_wrapper(const functor_wrapper& f) :
F(static_cast<const F&>(f)),
A(static_cast<const A&>(f))
{
}
};
/**
@ -283,14 +294,14 @@ namespace boost {
} 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
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_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.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
@ -304,23 +315,27 @@ namespace boost {
if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data);
new ((void*)&out_buffer.data) functor_type(*in_functor);
new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);
if (op == move_functor_tag) {
reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();
functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor();
}
} else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor();
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_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.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
@ -358,8 +373,10 @@ namespace boost {
// Clone the functor
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
// jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete.
const functor_type* f =
(const functor_type*)(in_buffer.obj_ptr);
static_cast<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) {
@ -372,14 +389,14 @@ namespace boost {
delete f;
out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
const BOOST_FUNCTION_STD_NS::type_info& check_type
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_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.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
@ -414,7 +431,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.type = &BOOST_SP_TYPEID(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return;
@ -463,7 +480,7 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
const functor_wrapper_type* f =
(const functor_wrapper_type*)(in_buffer.obj_ptr);
static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f);
@ -483,14 +500,14 @@ namespace boost {
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
const detail::sp_typeinfo& check_type
= *out_buffer.type.type;
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_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.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
@ -517,7 +534,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.type = &BOOST_SP_TYPEID(functor_type);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
return;
@ -618,14 +635,14 @@ public:
/** Determine if the function is empty (i.e., has no target). */
bool empty() const { return !vtable; }
/** Retrieve the type of the stored function object, or typeid(void)
/** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void)
if this is empty. */
const BOOST_FUNCTION_STD_NS::type_info& target_type() const
const detail::sp_typeinfo& target_type() const
{
if (!vtable) return typeid(void);
if (!vtable) return BOOST_SP_TYPEID(void);
detail::function::function_buffer type;
vtable->manager(functor, type, detail::function::get_functor_type_tag);
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.type.type;
}
@ -635,10 +652,10 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &typeid(Functor);
type_result.type.type = &BOOST_SP_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,
get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr);
}
@ -653,14 +670,14 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &typeid(Functor);
type_result.type.type = &BOOST_SP_TYPEID(Functor);
type_result.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
vtable->manager(functor, type_result,
get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
return (const Functor*)(type_result.obj_ptr);
return static_cast<const Functor*>(type_result.obj_ptr);
}
template<typename F>
@ -702,6 +719,15 @@ public:
#endif
public: // should be protected, but GCC 2.95.3 will fail to allow access
detail::function::vtable_base* get_vtable() const {
return reinterpret_cast<detail::function::vtable_base*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
}
bool has_trivial_copy_and_destroy() const {
return reinterpret_cast<std::size_t>(vtable) & 0x01;
}
detail::function::vtable_base* vtable;
mutable detail::function::function_buffer functor;
};
@ -877,4 +903,8 @@ namespace detail {
#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
#undef BOOST_FUNCTION_COMPARE_TYPE_ID
#if defined(BOOST_MSVC)
# pragma warning( pop )
#endif
#endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -21,7 +21,7 @@ namespace boost { namespace python { namespace objects {
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|| defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
|| !(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
#endif

View File

@ -11,6 +11,7 @@
// Note: this header is a header template and must NOT have multiple-inclusion
// protection.
#include <boost/function/detail/prologue.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#if defined(BOOST_MSVC)
# pragma warning( push )
@ -513,7 +514,7 @@ namespace boost {
if (f) {
// should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions
functor.func_ptr = (void (*)())(f);
functor.func_ptr = reinterpret_cast<void (*)()>(f);
return true;
} else {
return false;
@ -535,7 +536,7 @@ namespace boost {
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
if (f) {
this->assign_to(mem_fn(f), functor);
this->assign_to(boost::mem_fn(f), functor);
return true;
} else {
return false;
@ -548,7 +549,7 @@ namespace boost {
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
if (f) {
this->assign_to_a(mem_fn(f), functor, a);
this->assign_to_a(boost::mem_fn(f), functor, a);
return true;
} else {
return false;
@ -562,7 +563,7 @@ namespace boost {
void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
{
new ((void*)&functor.data) FunctionObj(f);
new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
}
template<typename FunctionObj,typename Allocator>
void
@ -624,14 +625,10 @@ namespace boost {
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;
return true;
} else {
return false;
}
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;
return true;
}
template<typename FunctionObj,typename Allocator>
bool
@ -678,6 +675,11 @@ namespace boost {
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
vtable_type;
vtable_type* get_vtable() const {
return reinterpret_cast<vtable_type*>(
reinterpret_cast<std::size_t>(vtable) & ~static_cast<size_t>(0x01));
}
struct clear_type {};
public:
@ -757,7 +759,7 @@ namespace boost {
if (this->empty())
boost::throw_exception(bad_function_call());
return static_cast<vtable_type*>(vtable)->invoker
return get_vtable()->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#else
@ -781,24 +783,26 @@ namespace boost {
operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
{
this->clear();
try {
BOOST_TRY {
this->assign_to(f);
} catch (...) {
} BOOST_CATCH (...) {
vtable = 0;
throw;
BOOST_RETHROW;
}
BOOST_CATCH_END
return *this;
}
template<typename Functor,typename Allocator>
void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
{
this->clear();
try {
BOOST_TRY{
this->assign_to_a(f,a);
} catch (...) {
} BOOST_CATCH (...) {
vtable = 0;
throw;
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#ifndef BOOST_NO_SFINAE
@ -823,12 +827,13 @@ namespace boost {
return *this;
this->clear();
try {
BOOST_TRY {
this->assign_to_own(f);
} catch (...) {
} BOOST_CATCH (...) {
vtable = 0;
throw;
BOOST_RETHROW;
}
BOOST_CATCH_END
return *this;
}
@ -847,7 +852,8 @@ namespace boost {
void clear()
{
if (vtable) {
reinterpret_cast<vtable_type*>(vtable)->clear(this->functor);
if (!this->has_trivial_copy_and_destroy())
get_vtable()->clear(this->functor);
vtable = 0;
}
}
@ -876,8 +882,11 @@ namespace boost {
{
if (!f.empty()) {
this->vtable = f.vtable;
f.vtable->manager(f.functor, this->functor,
boost::detail::function::clone_functor_tag);
if (this->has_trivial_copy_and_destroy())
this->functor = f.functor;
else
get_vtable()->base.manager(f.functor, this->functor,
boost::detail::function::clone_functor_tag);
}
}
@ -903,8 +912,15 @@ namespace boost {
static vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base;
else vtable = 0;
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else
vtable = 0;
}
template<typename Functor,typename Allocator>
@ -930,8 +946,15 @@ namespace boost {
static vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable.base;
else vtable = 0;
if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
if (boost::has_trivial_copy_constructor<Functor>::value &&
boost::has_trivial_destructor<Functor>::value &&
detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<detail::function::vtable_base *>(value);
} else
vtable = 0;
}
// Moves the value from the specified argument to *this. If the argument
@ -942,23 +965,23 @@ namespace boost {
if (&f == this)
return;
#if !defined(BOOST_NO_EXCEPTIONS)
try {
#endif
BOOST_TRY {
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)
if (this->has_trivial_copy_and_destroy())
this->functor = f.functor;
else
get_vtable()->base.manager(f.functor, this->functor,
boost::detail::function::move_functor_tag);
f.vtable = 0;
} else {
clear();
}
} catch (...) {
} BOOST_CATCH (...) {
vtable = 0;
throw;
BOOST_RETHROW;
}
#endif
BOOST_CATCH_END
}
};
@ -979,13 +1002,14 @@ namespace boost {
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
typename BOOST_FUNCTION_FUNCTION<
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
inline
BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
::operator()(BOOST_FUNCTION_PARMS) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return reinterpret_cast<const vtable_type*>(vtable)->invoker
return get_vtable()->invoker
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
}
#endif

View File

@ -8,6 +8,7 @@
# For more information, see http://www.boost.org/
project
: requirements <toolset>msvc:<asynch-exceptions>on
: source-location $(BOOST_ROOT)
;

View File

@ -128,6 +128,10 @@ test_main(int, char*[])
BOOST_CHECK(dealloc_count == 0);
fv.assign( &do_nothing, std::allocator<int>() );
fv.clear();
function0<void> fv2;
fv.assign(&do_nothing, std::allocator<int>() );
fv2.assign(fv, std::allocator<int>() );
return 0;
}

View File

@ -13,8 +13,8 @@
#include <string>
#include <utility>
using namespace boost;
using namespace std;
using boost::function;
using std::string;
int global_int;
@ -525,7 +525,7 @@ test_zero_args()
static void
test_one_arg()
{
negate<int> neg;
std::negate<int> neg;
function<int (int)> f1(neg);
BOOST_CHECK(f1(5) == -5);
@ -607,12 +607,12 @@ struct add_with_throw_on_copy {
add_with_throw_on_copy(const add_with_throw_on_copy&)
{
throw runtime_error("But this CAN'T throw");
throw std::runtime_error("But this CAN'T throw");
}
add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
{
throw runtime_error("But this CAN'T throw");
throw std::runtime_error("But this CAN'T throw");
}
};
@ -621,14 +621,38 @@ test_ref()
{
add_with_throw_on_copy atc;
try {
boost::function<int (int, int)> f(ref(atc));
boost::function<int (int, int)> f(boost::ref(atc));
BOOST_CHECK(f(1, 3) == 4);
}
catch(runtime_error e) {
catch(std::runtime_error e) {
BOOST_ERROR("Nonthrowing constructor threw an exception");
}
}
static void dummy() {}
static void test_empty_ref()
{
boost::function<void()> f1;
boost::function<void()> f2(boost::ref(f1));
try {
f2();
BOOST_ERROR("Exception didn't throw for reference to empty function.");
}
catch(std::runtime_error e) {}
f1 = dummy;
try {
f2();
}
catch(std::runtime_error e) {
BOOST_ERROR("Error calling referenced function.");
}
}
static void test_exception()
{
boost::function<int (int, int)> f;
@ -674,6 +698,7 @@ int test_main(int, char* [])
test_emptiness();
test_member_functions();
test_ref();
test_empty_ref();
test_exception();
test_implicit();
test_call();

View File

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