// 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 )
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
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) & ~(std::size_t)0x01);
+ }
+
struct clear_type {};
public:
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
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
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;
}
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;
}
}
{
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);
}
}
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 |= (std::size_t)0x01;
+ vtable = reinterpret_cast<detail::function::vtable_base *>(value);
+ } else
+ vtable = 0;
}
template<typename Functor,typename Allocator>
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 |= (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
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
}
};
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