c++11function源码分析
以VS2019 function源码为例分析。
class function:
template<class _Fty>
class function :public _Get_function_impl<_Fty>::type {// wrapper for callable objects
private:
using _Myba =typename _Get_function_impl<_Fty>::type;
public:
function()noexcept{// construct empty function wrapper
}
function(nullptr_t)noexcept{// construct empty function wrapper from null pointer
}
function(const function& _Right){// construct holding copy of _Right
this->_Ret_copy(_Right);
}
template<class _Fx,class=typename _Myba::template _Enable_if_callable_t<_Fx&, function>>
function(_Fx _Func){// construct wrapper holding copy of _Func
this->_Ret(_STD move(_Func));
}
...
};
class function继承⾃public _Get_function_impl<_Fty>::type
template<class _ _Types> \
struct _Get_function_impl<_Ret CALL_OPT(_)>{/* determine type from argument list */ \
using type = _Func_class<_Ret, _>; \
};
实际上是继承⾃class _Func_class。_Get_function_impl的作⽤是从函数定义类型拆分出返回值类型和参数类型。function只是做⼀层封装,具体的实现是在基类 _Func_class。
class _Func_class:
template<class _Ret,
< _Types>
class _Func_class :public _Arg_types<_>{// implement function template
public:
using result_type = _Ret;
using _Ptrt = _Func_ba<_Ret, _>;
_Func_class()noexcept{// construct without stored object
_Set(nullptr);
thereof}
_Ret operator()(_ _Args)const{// call through stored object
if(_Empty()){
_Xbad_function_call();
}
const auto _Impl =_Getimpl();
return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
}
~
_Func_class()noexcept{// destroy the object
_Tidy();
}
protected:
template<class _Fx>
void_Ret(_Fx&& _Val){// store copy of _Val
if(!_Test_callable(_Val)){// null member pointer/function pointer/std::function
return;// already empty
}
using _Impl = _Func_impl_no_alloc<decay_t<_Fx>, _Ret, _>;
_Ret_impl<_Impl>(_STD forward<_Fx>(_Val), _Is_large<_Impl>{});
}
template<class _Myimpl,class _Fx>
void_Ret_impl(_Fx&& _Val, true_type){// store copy of _Val, large (dynamically allocated) _Set(_Global_new<_Myimpl>(_STD forward<_Fx>(_Val)));
}
template<class _Myimpl,class _Fx>
void_Ret_impl(_Fx&& _Val, fal_type){// store copy of _Val, small (locally stored)
_Set(::new(_Getspace())_Myimpl(_STD forward<_Fx>(_Val)));
}
private:
union _Storage {// storage for small objects (basic_string is small)
max_align_t _Dummy1;// for maximum alignment
char _Dummy2[_Space_size];// to permit aliasing
起英文名网站_Ptrt* _Ptrs[_Small_object_num_ptrs];// _Ptrs[_Small_object_num_ptrs - 1] is rerved };
_Storage _Mystorage;
enum{ _EEN_IMPL = _Small_object_num_ptrs -1};// helper for expression evaluator
_Ptrt*_Getimpl()const noexcept{// get pointer to object
return _Mystorage._Ptrs[_Small_object_num_ptrs -1];
}
void_Set(_Ptrt* _Ptr)noexcept{// store pointer to object
_Mystorage._Ptrs[_Small_object_num_ptrs -1]= _Ptr;
}
void*_Getspace()noexcept{// get pointer to storage space
return&_Mystorage;
}
const void*_Getspace()const noexcept{// get pointer to storage space
return&_Mystorage;
}
};
class _Func_impl_no_alloc
template<class _Callable,class _ _Types>你好吗日语
class _Func_impl_no_alloc final
:public _Func_ba<_Rx, _>{// derived class for specific implementation types that don't u allocators
public:
using _Myba = _Func_ba<_Rx, _>;
using _Nothrow_move = is_nothrow_move_constructible<_Callable>;
template<class _Other,class= enable_if_t<!is_same_v<_Func_impl_no_alloc, decay_t<_Other>>>>
explicit_Func_impl_no_alloc(_Other&& _Val):_Callee(_STD forward<_Other>(_Val)){// construct
}
// dtor non-virtual due to _Delete_this()
private:
virtual _Myba*_Copy(void* _Where)const override {// return clone of *this
return_Clone(_Where, _Is_large<_Func_impl_no_alloc>{});
}
_Myba*_Clone(void*, true_type)const{// return clone of *this, large (dynamically allocated)
return _Global_new<_Func_impl_no_alloc>(_Callee);
}
_Myba*_Clone(void* _Where, fal_type)const{// return clone of *this, small (locally stored)
return::new(_Where)_Func_impl_no_alloc(_Callee);
}
virtual _Myba*_Move(void* _Where) override {// return clone of *this
return::new(_Where)_Func_impl_no_alloc(_STD move(_Callee));
}
virtual _Rx _Do_call(_Types&&... _Args) override {// call wrapped function
return _Invoker_ret<_Rx>::_Call(_Callee, _STD forward<_Types>(_Args)...);
}
_Callable _Callee;
};
rendipity我们从template <class _Fx, class = typename _Myba::template _Enable_if_callable_t<_Fx&, function>> function(_Fx _Func)这个构造函数⼊⼿。调⽤到基类_Func_class的template void _Ret(_Fx&& _Val)函数。这个函数中关键下⾯两句代码:
using _Impl = _Func_impl_no_alloc<decay_t<_Fx>, _Ret, _>;
_Ret_impl<_Impl>(_STD forward<_Fx>(_Val), _Is_large<_Impl>{});
_Is_large的定义:
constexpr int _Small_object_num_ptrs =6+16/sizeof(void*);
constexpr size_t _Space_size =(_Small_object_num_ptrs -1)*sizeof(void*);
template<class _Impl>// determine whether _Impl must be dynamically allocated
using _Is_large = bool_constant<(_Space_size <sizeof(_Impl))||!_Impl::_Nothrow_move::value>;
如果_Impl类的size⼤于_Space_size则为true,否则为fal。如果是64位系统,不难算出_Small_object_num_ptrs的⼤⼩为8,
_Space_size的⼤⼩则为78=56,也就是7个指针⼤⼩。
再看类中成员变量_Mystorage的定义:
union _Storage { // storage for small objects (basic_string is small)
swinging
max_align_t _Dummy1; // for maximum alignment
char _Dummy2[_Space_size]; // to permit aliasing
_Ptrt _Ptrs[_Small_object_num_ptrs]; // _Ptrs[_Small_object_num_ptrs - 1] is rerved
amadori};
_Ptrs为8个指针⼤⼩空间的指针数组。_Dummy2为7个指针⼤⼩空间的char数组。
所以,如果_Impl类的size⼩于等于7个指针⼤⼩,调⽤
template<class _Myimpl,class _Fx>
void_Ret_impl(_Fx&& _Val, fal_type){// store copy of _Val, small (locally stored)
_Set(::new(_Getspace())_Myimpl(_STD forward<_Fx>(_Val)));
}
这⾥⽤到了placement new,将_Myimpl对象放到成员变量_Mystorage指向空间的前56个字节,也即_Dummy2。然后调⽤_Set函数将_Myimpl对象指针赋值给数组_Ptrs的最后⼀个元素_Ptrs[_Small_object_num_ptrs - 1]。
如果_Impl类的size⼤于7个指针⼤⼩,调⽤
template<class _Myimpl,class _Fx>
void_Ret_impl(_Fx&& _Val, true_type){// store copy of _Val, large (dynamically allocated)
_Set(_Global_new<_Myimpl>(_STD forward<_Fx>(_Val)));
}
new出⼀个_Myimpl对象,然后调⽤_Set函数将_Myimpl对象指针赋值给数组_Ptrs的最后⼀个元素_Ptr
s[_Small_object_num_ptrs -1]。
这时传⼊的函数对象保存在_Myimpl对象中,也即数组_Ptrs的最后⼀个元素_Ptrs[_Small_object_num_ptrs - 1]指向的地址。
⼀般情况下_Impl类中传⼊⼀个函数指针,size都不会很⼤。那么什么时候它的size会⼤于7个指针⼤⼩呢?当_Impl类中传⼊⼀个类或者结构体对象时,它的size就可能很⼤。这种情形⼀般是调⽤类对象的operator()。
另外类中_Ret_alloc是function传⼊⾃定义allocator的情形,这⾥不做解析。
从function的使⽤经验可知,⼀个function构造完成,调⽤的时候是operator()。这个operator()运算符重载函数在基类_Func_class中实现的。
const auto _Impl =_Getimpl();
return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
_Getimpl函数其实是取得之前保存的_Myimpl对象指针。然后调⽤class _Func_impl_no_alloc的_Do_call函数。
_Invoker_ret<_Rx>::_Call(_Callee, _STD forward<_Types>(_Args)...);
_Callee为之前保存的函数指针,_Args…为调⽤function是传⼊的可变参数。
_Invoker_ret是⼀个结构体,_Call是它的static成员函数。
// 泛化版本
template<class _Rx,bool= is_void_v<_Rx>>
struct _Invoker_ret {};// helper to give INVOKE an explicit return type; avoids undesirable Expression SFINAE
struct _Unforced {};// tag to distinguish bind() from bind<R>()
// 返回值为void的特化版本(部分具体化)
template<class _Cv_void>
struct _Invoker_ret<_Cv_void,true>{// lected for _Rx being cv void
template& _Valtys>
static void_Call(_Valtys&&... _Vals){// INVOKE, "implicitly" converted to void
_STD invoke(_STD forward<_Valtys>(_Vals)...);
}
};
// 返回值为⾮void的特化版本(部分具体化)
template<class _Rx>
struct _Invoker_ret<_Rx,fal>{// lected for all _Rx other than cv void and _Unforced
template& _Valtys>
static _Rx _Call(_Valtys&&... _Vals){// INVOKE, implicitly converted to _Rx
return _STD invoke(_STD forward<_Valtys>(_Vals)...);六级作文句型
}
};
// 特化版本,function这⾥不会调⽤到,bind中会⽤到,_Unforced只是⼀个tag的作⽤。
template<>
struct _Invoker_ret<_Unforced,fal>{// lected for _Rx being _Unforced
template& _Valtys>
static auto_Call(_Valtys&&... _Vals)
->decltype(_STD invoke(_STD forward<_Valtys>(_Vals)...)){// INVOKE, unchanged小学英语故事
return _STD invoke(_STD forward<_Valtys>(_Vals)...);
}
};
看源码⽐较容易理解。最终通过invoke调⽤。
invoke具体实现:
#define _IMPLEMENT_INVOKE(NAME_PREFIX, CONSTEXPR) \
/* FUNCTION TEMPLATE invoke */
// ⼀个对象的成员函数 \
struct_CONCAT(NAME_PREFIX, _Invoker_pmf_object){/* INVOKE a pointer to member function on an object */ \ template<class _Decayed,class _ _Types2> \
static CONSTEXPR auto_Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) \
_NOEXCEPT_COND(noexcept((_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...))) \ ->decltype((_STD forward<_Ty1>(_Arg1).*_Pmf)( \
_STD forward<_Types2>(_Args2)...)){/* INVOKE a pointer to member function on an object */ \ return(_STD forward<_Ty1>(_Arg1).*_Pmf)(_STD forward<_Types2>(_Args2)...); \
} \
}; \
// reference_wrapper对象的成员函数 \
struct_CONCAT( \
NAME_PREFIX, _Invoker_pmf_refwrap){/* INVOKE a pointer to member function on a reference_wrapper */ \ template<class _Decayed,class _ _Types2> \
economy是什么意思>形容词大全static CONSTEXPR auto_Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) \
_NOEXCEPT_COND(noexcept((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2
>(_Args2)...))) \ ->decltype((_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>( \
_Args2)...)){/* INVOKE a pointer to member function on a reference_wrapper */ \ return(_STD forward<_Ty1>(_Arg1).get().*_Pmf)(_STD forward<_Types2>(_Args2)...); \
} \
}; \
// ⼀个智能指针或者普通指针指向对象的成员函数 \
struct_CONCAT(NAME_PREFIX, _Invoker_pmf_pointer){/* INVOKE a pointer to member function on a [smart] pointer */ \