首先我假定大家已熟悉function的接口,我不打算把boost的源码完全分析,只分析部分。我的boost版本是1_57_0。
我们要能够存储函数指针,成员函数指针,仿函数,函数指针直接存储函数指针原始值,成员函数指针存储为仿函数,仿函数直接new一个拷贝即可。function_buffer解决存储问题,定义为union为了节省内存,都老生常谈了。boost比我实现的缩水版本要多了很多类型,成员函数指针我一开始以为会存储在function_buffer中,事实上我多心了,function直接把成员函数封装为仿函数,再调用仿函数存储,但是调用成员函数的时候,是使用了bound_memfunc_ptr的。这里要说的是,缩水版的function并没有考虑小对象(所谓的小对象是指仿函数在内存中的size比function_buffer小)的内存优化问题,如果new一个新的对象,频繁new小对象并不是好的选择,这时候直接在function_buffer上定位new。
class X;
union function_buffer
{
// 仿函数的指针
mutable void* obj_ptr;
// 指向std::type_info的指针
struct type_t {
// (get_functor_type_tag, check_functor_type_tag).
const detail::sp_typeinfo* type;
// Whether the type is const-qualified.
bool const_qualified;
// Whether the type is volatile-qualified.
bool volatile_qualified;
} type;
// 函数指针
mutable void(*func_ptr)();
// 成员函数指针
struct bound_memfunc_ptr_t {
void (X::*memfunc_ptr)(int);
void* obj_ptr;
} bound_memfunc_ptr;
// 仿函数引用类型
struct obj_ref_t {
mutable void* obj_ptr;
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;
// 小对象内存优化时使用
mutable char data;
};
接着看vtable_base类型,这个是操作function_buffer的,可以克隆、移动、销毁、检查类型、获取类型。
// The operation type to perform on the given functor/function pointer
enum functor_manager_operation_type {
clone_functor_tag,
move_functor_tag,
destroy_functor_tag,
check_functor_type_tag,
get_functor_type_tag
};
/**
* Stores the "manager" portion of the vtable for a
* boost::function object.
*/
struct vtable_base
{
void(*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer,
functor_manager_operation_type op);
};
首先是仿函数引用类型,肯定是操作function_buffer的obj_ref
template
struct reference_manager
{
static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
switch (op) {
case clone_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref;
return;
case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref;
in_buffer.obj_ref.obj_ptr = 0;
return;
case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0;
return;
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
// cv-qualifiers, but we can't take them away.
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
|| out_buffer.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
else
out_buffer.obj_ptr = 0;
}
return;
case get_functor_type_tag:
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;
}
}
};
接着是函数指针,主要对func_ptr操作
template
struct functor_manager_common
{
typedef Functor functor_type;
// Function pointers
static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.func_ptr = 0;
} else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type
= *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
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
小对象的仿函数,由于使用定位new,所以需要手动调用析构函数。
// Function objects that fit in the small-object buffer.
static inline void
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op)
{
if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor =
reinterpret_cast(&in_buffer.data);
new (reinterpret_cast(&out_buffer.data)) functor_type(*in_functor);
if (op == move_functor_tag) {
functor_type* f = reinterpret_cast(&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.
functor_type* f = reinterpret_cast(&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 detail::sp_typeinfo& check_type
= *out_buffer.type.type;
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 = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
仿函数,需要从堆上分配内存的,
static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_)
{
if (op == clone_functor_tag) {
// 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 =
static_cast(in_buffer.obj_ptr);
functor_type* new_f = new functor_type(*f);
out_buffer.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.obj_ptr = 0;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */
functor_type* f =
static_cast(out_buffer.obj_ptr);
delete f;
out_buffer.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
const detail::sp_typeinfo& check_type
= *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
out_buffer.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
}
}
可能比较奇怪的是多了个参数mpl::false_,这个参数是通过下面的函数来判断的。
template
struct function_allows_small_object_optimization
{
BOOST_STATIC_CONSTANT
(bool,
value = ((sizeof(F) <= sizeof(function_buffer) &&
(alignment_of::value
% alignment_of::value == 0))));
};
并没有成员函数的manage版本,是因为成员函数会转化为仿函数。
然后是所有function的基类,主要是负责存储。这里比较奇怪的是使用vtable的最后一个bit是否是1来作为trivial的判断(就是小对象),如果是我自己编写,我会使用bool变量来标明,我一开始有疑问,当vtable_base指针的最后一个bit是1岂不是全部出错,调试发现该指针的内存地址的最后一个bit始终为0,这个可能与编译器的对齐方式有关,因为vtable_base的指针是一个函数的static变量。
class function_base
{
public:
function_base() : vtable(0) { }
//...
detail::function::vtable_base* get_vtable() const {
return reinterpret_cast(
reinterpret_cast(vtable) & ~static_cast(0x01));
}
bool has_trivial_copy_and_destroy() const {
return reinterpret_cast(vtable) & 0x01;
}
public:
vtable_base* vtable;
mutable function_buffer functor;
};
接下来是get_function_tag,用来萃取函数类型,是函数指针,成员函数指针,或者仿函数。
struct function_ptr_tag {};
struct function_obj_tag {};
struct member_ptr_tag {};
struct function_obj_ref_tag {};
template
class get_function_tag
{
typedef typename mpl::if_c<(is_pointer::value),
function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag;
typedef typename mpl::if_c<(is_member_pointer::value),
member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
typedef typename mpl::if_c<(is_reference_wrapper::value),
function_obj_ref_tag,
ptr_or_obj_or_mem_tag>::type or_ref_tag;
public:
typedef or_ref_tag type;
};
if_c是mpl函数(博客不对任何mpl展开分析),用伪代码表示如下,其他mpl函数如函数名,value值是true或者false,大家自行把各个情况放入上面验证,至于mpl可以自行搜索,c++reference上也给出了可能实现。
if_c::type = int
if_c::type = double
function_base至此所有的代码已经完毕,基本上是完成了对function_buffer的操作,主要是实现function的拷贝、移动、类型比较等。不管function是什么类型,这部分操作是共用的,定义一个基类的确很有必要。
接下来以一元function为例,分析代码。
basic_vtable1
template
struct basic_vtable1
{
typedef R result_type;
typedef result_type(*invoker_type)(function_buffer&,T0);
template
//将f存储入function_buffer
bool assign_to(F f, function_buffer& functor) const
{
typedef typename get_function_tag::type tag;//萃取类型
return assign_to(f, functor, tag());//根据不同的类型,调用不同的重载函数,Policies design
}
void clear(function_buffer& functor) const
{
if (base.manager)//调用destroy
base.manager(functor, functor, destroy_functor_tag);
}
private:
template
bool assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
{
// 函数指针,直接赋值
this->clear(functor);
if (f) {
functor.func_ptr = reinterpret_cast(f);
return true;
}
else {
return false;
}
}
template
bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
{
//成员函数指针,先使用mem_fn返回仿函数,再调用前面的接口来存储
if (f) {
this->assign_to(boost::mem_fn(f), functor);
return true;
}
else {
return false;
}
}
template
bool assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
{
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
//仿函数对象,根据仿函数对象的size,决定是否需要重新分配内存,如果仿函数内存不比function_buffer大,那么可以不用分配新的内存
assign_functor(f, functor,mpl::bool_<(function_allows_small_object_optimization::value)>());
return true;
}
else {
return false;
}
}
template
void assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
{
new (reinterpret_cast(&functor.data)) FunctionObj(f);//定位new
}
template
void assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
{
functor.obj_ptr = new FunctionObj(f);//copy
}
template
bool assign_to(const reference_wrapper& f,
function_buffer& functor, function_obj_ref_tag) const
{
//函数对象引用
functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.obj_ref.is_const_qualified = is_const::value;
functor.obj_ref.is_volatile_qualified = is_volatile::value;
return true;
}
public:
vtable_base base;
invoker_type invoker;//调用的函数指针
};
有了basic_vtable1,仿函数的存储和调用都齐全了。当然还差invoke的具体:
template
struct function_invoker1
{
static R invoke(function_buffer& function_ptr,T0 a0)
{
FunctionPtr f = reinterpret_cast(function_ptr.func_ptr);
return f(a0);//函数指针直接转换类型后调用
}
};
template
struct function_obj_invoker1
{
static R invoke(function_buffer& function_obj_ptr,T0 a0)
{
FunctionObj* f;
if (function_allows_small_object_optimization::value)
f = reinterpret_cast(&function_obj_ptr.data);
else
f = reinterpret_cast(function_obj_ptr.obj_ptr);
return (*f)(a0);//仿函数分两种情况,一种小对象转换data,否则转换obj_ptr
}
};
template
struct function_ref_invoker1
{
static R invoke(function_buffer& function_obj_ptr,T0 a0)
{
FunctionObj* f =reinterpret_cast(function_obj_ptr.obj_ptr);
return (*f)(a0);//仿函数引用
}
};
//成员函数的调用很奇葩,前面manage的时候是使用定位new,原本我以为这里应该再调用仿函数来调用
//这里直接将data转换为MemberPtr,这是假定成员函数的仿函数的第一个成员变量就是MemberPtr
template
struct function_mem_invoker1
{
static R invoke(function_buffer& function_obj_ptr,T0 a0)
{
MemberPtr* f =reinterpret_cast(&function_obj_ptr.data);
return boost::mem_fn(*f)(a0);
}
};
mem_fn将返回仿函数mf1
template
_mfi::mf1 mem_fn(R(T::*f) (A1))
{
return _mfi::mf1(f);
}
mf1肯定是个仿函数,如下,只有一个成员变量f_(成员函数指针类型)。
template class mf1
{
public:
typedef R result_type;
typedef T * first_argument_type;
typedef A1 second_argument_type;
private:
typedef R(T::*F) (A1);
F f_;
template R call(U & u, T const *, B1 & b1) const
{
return (u.*f_)(b1);
}
template R call(U & u, void const *, B1 & b1) const
{
return (get_pointer(u)->*f_)(b1);
}
public:
explicit mf1(F f) : f_(f) {}
R operator()(T * p, A1 a1) const
{
return (p->*f_)(a1);//R(T*,A1)最终使用成员函数指针来调用
}
template R operator()(U & u, A1 a1) const
{
U const * p = 0;
return call(u, p, a1);
}
template R operator()(U const & u, A1 a1) const
{
U const * p = 0;
return call(u, p, a1);
}
R operator()(T & t, A1 a1) const
{
return (t.*f_)(a1);//R(T&,A1)
}
bool operator==(mf1 const & rhs) const
{
return f_ == rhs.f_;
}
bool operator!=(mf1 const & rhs) const
{
return f_ != rhs.f_;
}
};
接下来是function1,代码太多,先分为几部分,最后上所有代码,先分析构造
function1() : function_base() { }
template
function1(Functor f, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
function_base()
{
this->assign_to(f);
}
template
function1(Functor f, Allocator a
, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
function_base()
{
this->assign_to_a(f, a);
}
function1(clear_type*) : function_base() { }
function1(const function1& f) : function_base()
{
this->assign_to_own(f);
}
function1(function1&& f) : function_base()
{
this->move_assign(f);
}
各种assign_to
void assign_to_own(const function1& f)
{
if (!f.empty()) {
this->vtable = f.vtable;
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);
}
}
template
void assign_to(Functor f)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag::type tag;
typedef detail::function::get_invoker1 get_invoker;
typedef typename get_invoker::
template apply
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast(&stored_vtable.base);
if (boost::has_trivial_copy_constructor::value &&
boost::has_trivial_destructor::value &&
detail::function::function_allows_small_object_optimization::value)
value |= static_cast(0x01);
vtable = reinterpret_cast(value);
}
else
vtable = 0;
}
template
void assign_to_a(Functor f, Allocator a)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag::type tag;
typedef detail::function::get_invoker1 get_invoker;
typedef typename get_invoker::
template apply_a
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast(&stored_vtable.base);
if (boost::has_trivial_copy_constructor::value &&
boost::has_trivial_destructor::value &&
detail::function::function_allows_small_object_optimization::value)
value |= static_cast(0x01);
vtable = reinterpret_cast(value);
}
else
vtable = 0;
}
void move_assign(function1& f)
{
if (&f == this)
return;
{ try {
if (!f.empty()) {
this->vtable = f.vtable;
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 (...) {
vtable = 0;
throw;;
}
}
}
operator=
function1& operator=(clear_type*)
{
this->clear();
return *this;
}
function1& operator=(const function1& f)
{
if (&f == this)
return *this;
this->clear();
{ try {
this->assign_to_own(f);
}
catch (...) {
vtable = 0;
throw;;
}
}
return *this;
}
function1& operator=(function1&& f)
{
if (&f == this)
return *this;
this->clear();
{ try {
this->move_assign(f);
}
catch (...) {
vtable = 0;
throw;;
}
}
return *this;
}
所谓的safe bool 惯用法,在C++11下只需要explicit operator bool即可。
private:
struct dummy {
void nonnull() {}
};
typedef void (dummy::*safe_bool)();
public:
operator safe_bool () const
{
return (this->empty()) ? 0 : &dummy::nonnull;
}
bool operator!() const
{
return this->empty();
}
当然,还得重载operator()
result_type operator()(T0 a0) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return get_vtable()->invoker
(this->functor, a0);
}
写到这,function1具备了function的所有特征,function再写就多余了,事实上funcation1多余,
template
class function
: public function1
{
typedef function1 base_type;
typedef function self_type;
struct clear_type {};
public:
function() : base_type() {}
template
function(Functor f
, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
base_type(f)
{
}
template
function(Functor f, Allocator a
, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
base_type(f, a)
{
}
function(clear_type*) : base_type() {}
function(const self_type& f) : base_type(static_cast(f)) {}
function(const base_type& f) : base_type(static_cast(f)) {}
function(self_type&& f) : base_type(static_cast(f)) {}
function(base_type&& f) : base_type(static_cast(f)) {}
self_type& operator=(const self_type& f)
{
self_type(f).swap(*this);
return *this;
}
self_type& operator=(self_type&& f)
{
self_type(static_cast(f)).swap(*this);
return *this;
}
template
typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
self_type&>::type
operator=(Functor f)
{
self_type(f).swap(*this);
return *this;
}
self_type& operator=(clear_type*)
{
this->clear();
return *this;
}
self_type& operator=(const base_type& f)
{
self_type(f).swap(*this);
return *this;
}
self_type& operator=(base_type&& f)
{
self_type(static_cast(f)).swap(*this);
return *this;
}
};
上述代码基本就是重新写了构造函数和operator=。
文末,附上function1的所有源码
template
class function1 : public function_base, public std::unary_function
{
public:
typedef R result_type;
private:
typedef boost::detail::function::basic_vtable1 vtable_type;
vtable_type* get_vtable() const {
return reinterpret_cast(
reinterpret_cast(vtable) & ~static_cast(0x01));
}
struct clear_type {};
public:
static const int args = 1;
template
struct sig
{
typedef result_type type;
};
typedef T0 argument_type;
static const int arity = 1;
typedef T0 arg1_type;
typedef function1 self_type;
function1() : function_base() { }
template
function1(Functor f, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
function_base()
{
this->assign_to(f);
}
template
function1(Functor f, Allocator a
, typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
int>::type = 0
) :
function_base()
{
this->assign_to_a(f, a);
}
function1(clear_type*) : function_base() { }
function1(const function1& f) : function_base()
{
this->assign_to_own(f);
}
function1(function1&& f) : function_base()
{
this->move_assign(f);
}
~function1() { clear(); }
result_type operator()(T0 a0) const
{
if (this->empty())
boost::throw_exception(bad_function_call());
return get_vtable()->invoker
(this->functor, a0);
}
template
typename enable_if_c<
(boost::type_traits::ice_not<
(is_integral::value)>::value),
function1&>::type
operator=(Functor f)
{
this->clear();
{ try {
this->assign_to(f);
}
catch (...) {
vtable = 0;
throw;;
}
}
return *this;
}
template
void assign(Functor f, Allocator a)
{
this->clear();
{ try {
this->assign_to_a(f, a);
}
catch (...) {
vtable = 0;
throw;;
}
}
}
function1& operator=(clear_type*)
{
this->clear();
return *this;
}
function1& operator=(const function1& f)
{
if (&f == this)
return *this;
this->clear();
{ try {
this->assign_to_own(f);
}
catch (...) {
vtable = 0;
throw;;
}
}
return *this;
}
function1& operator=(function1&& f)
{
if (&f == this)
return *this;
this->clear();
{ try {
this->move_assign(f);
}
catch (...) {
vtable = 0;
throw;;
}
}
return *this;
}
void swap(function1& other)
{
if (&other == this)
return;
function1 tmp;
tmp.move_assign(*this);
this->move_assign(other);
other.move_assign(tmp);
}
void clear()
{
if (vtable) {
if (!this->has_trivial_copy_and_destroy())
get_vtable()->clear(this->functor);
vtable = 0;
}
}
private:
struct dummy {
void nonnull() {}
};
typedef void (dummy::*safe_bool)();
public:
operator safe_bool () const
{
return (this->empty()) ? 0 : &dummy::nonnull;
}
bool operator!() const
{
return this->empty();
}
private:
void assign_to_own(const function1& f)
{
if (!f.empty()) {
this->vtable = f.vtable;
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);
}
}
template
void assign_to(Functor f)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag::type tag;
typedef detail::function::get_invoker1 get_invoker;
typedef typename get_invoker::
template apply
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) {
std::size_t value = reinterpret_cast(&stored_vtable.base);
if (boost::has_trivial_copy_constructor::value &&
boost::has_trivial_destructor::value &&
detail::function::function_allows_small_object_optimization::value)
value |= static_cast(0x01);
vtable = reinterpret_cast(value);
}
else
vtable = 0;
}
template
void assign_to_a(Functor f, Allocator a)
{
using detail::function::vtable_base;
typedef typename detail::function::get_function_tag::type tag;
typedef detail::function::get_invoker1 get_invoker;
typedef typename get_invoker::
template apply_a
handler_type;
typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type;
static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast(&stored_vtable.base);
if (boost::has_trivial_copy_constructor::value &&
boost::has_trivial_destructor::value &&
detail::function::function_allows_small_object_optimization::value)
value |= static_cast(0x01);
vtable = reinterpret_cast(value);
}
else
vtable = 0;
}
void move_assign(function1& f)
{
if (&f == this)
return;
{ try {
if (!f.empty()) {
this->vtable = f.vtable;
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 (...) {
vtable = 0;
throw;;
}
}
}
};