下面是我的std::function的阅读笔记:
// CLASS TEMPLATE function
template
class function : public _Get_function_impl<_Fty>::type { // wrapper for callable objects // 注意这里,继承的是_Get_function_impl<_Fty>::type ,即_Func_class<_Ret, _Types...>;
private:
using _Mybase = typename _Get_function_impl<_Fty>::type;
public:
function() noexcept {}
function(nullptr_t) noexcept {}
function(const function& _Right) {
this->_Reset_copy(_Right);
}
template >
function(_Fx _Func) {
this->_Reset(_STD move(_Func));
}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template
function(allocator_arg_t, const _Alloc&) noexcept {}
template
function(allocator_arg_t, const _Alloc&, nullptr_t) noexcept {}
template
function(allocator_arg_t, const _Alloc& _Ax, const function& _Right) {
this->_Reset_alloc(_Right, _Ax);
}
template >
function(allocator_arg_t, const _Alloc& _Ax, _Fx _Func) {
this->_Reset_alloc(_STD move(_Func), _Ax);
}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
function& operator=(const function& _Right) {
function(_Right).swap(*this);
return *this;
}
function(function&& _Right) noexcept {
this->_Reset_move(_STD move(_Right));
}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template
function(allocator_arg_t, const _Alloc& _Al, function&& _Right) {
this->_Reset_alloc(_STD move(_Right), _Al);
}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
function& operator=(function&& _Right) noexcept /* strengthened */ {
if (this != _STD addressof(_Right)) {
this->_Tidy();
this->_Reset_move(_STD move(_Right));
}
return *this;
}
template &, function>>
function& operator=(_Fx&& _Func) {
function(_STD forward<_Fx>(_Func)).swap(*this);
return *this;
}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template
void assign(_Fx&& _Func, const _Alloc& _Ax) {
function(allocator_arg, _Ax, _STD forward<_Fx>(_Func)).swap(*this);
}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
function& operator=(nullptr_t) noexcept {
this->_Tidy();
return *this;
}
template
function& operator=(reference_wrapper<_Fx> _Func) noexcept {
this->_Tidy();
this->_Reset(_Func);
return *this;
}
void swap(function& _Right) noexcept {
this->_Swap(_Right);
}
explicit operator bool() const noexcept {
return !this->_Empty();
}
#if _HAS_STATIC_RTTI
_NODISCARD const type_info& target_type() const noexcept {
return this->_Target_type();
}
template
_NODISCARD _Fx* target() noexcept {
return reinterpret_cast<_Fx*>(const_cast(this->_Target(typeid(_Fx))));
}
template
_NODISCARD const _Fx* target() const noexcept {
return reinterpret_cast(this->_Target(typeid(_Fx)));
}
#else // _HAS_STATIC_RTTI
const type_info& target_type() const noexcept = delete; // requires static RTTI
template
_Fx* target() noexcept = delete; // requires static RTTI
template
const _Fx* target() const noexcept = delete; // requires static RTTI
#endif // _HAS_STATIC_RTTI
};
接下来看其基类实现:
// CLASS TEMPLATE _Func_class --------也就是std::function的基类
template
class _Func_class : public _Arg_types<_Types...> {
public:
using result_type = _Ret;
using _Ptrt = _Func_base<_Ret, _Types...>;// 这个基类定义了一系列的虚函数
_Func_class() noexcept {
_Set(nullptr);
}
_Ret operator()(_Types... _Args) const {
if (_Empty()) {
_Xbad_function_call();
}
const auto _Impl = _Getimpl();
return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
}
~_Func_class() noexcept {
_Tidy();
}
protected:
template
using _Enable_if_callable_t =
enable_if_t, _Function>>, _Is_invocable_r<_Ret, _Fx, _Types...>>>;
bool _Empty() const noexcept {
return !_Getimpl();
}
void _Reset_copy(const _Func_class& _Right) { // copy _Right's stored object
if (!_Right._Empty()) {
_Set(_Right._Getimpl()->_Copy(&_Mystorage));
}
}
void _Reset_move(_Func_class&& _Right) noexcept { // move _Right's stored object
if (!_Right._Empty()) {
if (_Right._Local()) { // move and tidy
_Set(_Right._Getimpl()->_Move(&_Mystorage));
_Right._Tidy();
} else { // steal from _Right
_Set(_Right._Getimpl());
_Right._Set(nullptr);
}
}
}
template
void _Reset(_Fx&& _Val) { // store copy of _Val
if (!_Test_callable(_Val)) { // null member pointer/function pointer/std::function
return; // already empty
}
/*
// FUNCTION TEMPLATE _Global_new
template
_Ty* _Global_new(_Types&&... _Args) { // acts as "new" while disallowing user overload selection
struct _Guard_type {
void* _Result;
~_Guard_type() {
if (_Result) {
_Deallocate<_New_alignof<_Ty>>(_Result, sizeof(_Ty));
}
}
};
_Guard_type _Guard{_Allocate<_New_alignof<_Ty>>(sizeof(_Ty))};
::new (_Guard._Result) _Ty(_STD forward<_Types>(_Args)...);
return static_cast<_Ty*>(_STD exchange(_Guard._Result, nullptr));// 这种写法,确保了异常安全,太牛皮了
}
*/
using _Impl = _Func_impl_no_alloc, _Ret, _Types...>;// 注意下面的_Set 对应的参数类型为接口指针,而这里是模板类,看模板类的声明可以发现其继承了_Func_base<_Rx, _Types...>
if
_CONSTEXPR_IF(_Is_large<_Impl>) {
// dynamically allocate _Val
_Set(_Global_new<_Impl>(_STD forward<_Fx>(_Val)));// 全局申请操作
}
else {
// store _Val in-situ
_Set(::new (static_cast(&_Mystorage)) _Impl(_STD forward<_Fx>(_Val)));// placement new 操作
}
}
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
template
void _Reset_alloc(_Fx&& _Val, const _Alloc& _Ax) { // store copy of _Val with allocator
if (!_Test_callable(_Val)) { // null member pointer/function pointer/std::function
return; // already empty
}
using _Myimpl = _Func_impl, _Alloc, _Ret, _Types...>;
if
_CONSTEXPR_IF(_Is_large<_Myimpl>) {
// dynamically allocate _Val
using _Alimpl = _Rebind_alloc_t<_Alloc, _Myimpl>;
_Alimpl _Al(_Ax);
_Alloc_construct_ptr<_Alimpl> _Constructor{_Al};
_Constructor._Allocate();
_Construct_in_place(*_Constructor._Ptr, _STD forward<_Fx>(_Val), _Ax);
_Set(_Unfancy(_Constructor._Release()));
}
else {
// store _Val in-situ
const auto _Ptr = reinterpret_cast<_Myimpl*>(&_Mystorage);
_Construct_in_place(*_Ptr, _STD forward<_Fx>(_Val), _Ax);
_Set(_Ptr);
}
}
#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT
void _Tidy() noexcept {
if (!_Empty()) { // destroy callable object and maybe delete it
_Getimpl()->_Delete_this(!_Local());
_Set(nullptr);
}
}
void _Swap(_Func_class& _Right) noexcept { // swap contents with contents of _Right
if (!_Local() && !_Right._Local()) { // just swap pointers
_Ptrt* _Temp = _Getimpl();
_Set(_Right._Getimpl());
_Right._Set(_Temp);
} else { // do three-way move
_Func_class _Temp;
_Temp._Reset_move(_STD move(*this));
_Reset_move(_STD move(_Right));
_Right._Reset_move(_STD move(_Temp));
}
}
#if _HAS_STATIC_RTTI
const type_info& _Target_type() const noexcept {
return _Getimpl() ? _Getimpl()->_Target_type() : typeid(void);
}
const void* _Target(const type_info& _Info) const noexcept {
return _Getimpl() ? _Getimpl()->_Target(_Info) : nullptr;
}
#endif // _HAS_STATIC_RTTI
private:
bool _Local() const noexcept { // test for locally stored copy of object
return _Getimpl() == static_cast(&_Mystorage);// 判断是否是本地存储,如果内部存储的空间地址就是_Mystorage的地址了,肯定就是本地的了
}
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 reserved
};
_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];// 对应下面的_Set函数,这里有一个读取的动作
}
void _Set(_Ptrt* _Ptr) noexcept { // store pointer to object
_Mystorage._Ptrs[_Small_object_num_ptrs - 1] = _Ptr;// 最后一个位置,需要存储我们的接口指针,因此,在计算是否超过存储空间大小的时候,需要去掉这一块的大小
}
};
其接口定义和实现类为:
接口定义
// CLASS TEMPLATE _Func_base
template
class __declspec(novtable) _Func_base { // abstract base for implementation types
public:
virtual _Func_base* _Copy(void*) const = 0;
virtual _Func_base* _Move(void*) noexcept = 0;
virtual _Rx _Do_call(_Types&&...) = 0;
virtual const type_info& _Target_type() const noexcept = 0;
virtual void _Delete_this(bool) noexcept = 0;
#if _HAS_STATIC_RTTI
const void* _Target(const type_info& _Info) const noexcept {
return _Target_type() == _Info ? _Get() : nullptr;
}
#endif // _HAS_STATIC_RTTI
_Func_base() = default;
_Func_base(const _Func_base&) = delete;
_Func_base& operator=(const _Func_base&) = delete;
// dtor non-virtual due to _Delete_this()
private:
virtual const void* _Get() const noexcept = 0;
};
实现:
// CLASS TEMPLATE _Func_impl_no_alloc
template
class _Func_impl_no_alloc final : public _Func_base<_Rx, _Types...> {
// derived class for specific implementation types that don't use allocators
public:
using _Mybase = _Func_base<_Rx, _Types...>;
using _Nothrow_move = is_nothrow_move_constructible<_Callable>;
template >>>
explicit _Func_impl_no_alloc(_Other&& _Val) : _Callee(_STD forward<_Other>(_Val)) {}
// dtor non-virtual due to _Delete_this()
private:
virtual _Mybase* _Copy(void* _Where) const override {
if
_CONSTEXPR_IF(_Is_large<_Func_impl_no_alloc>) {// 构造的时候,如果太大了,就需要动态申请内存了
(void) _Where;
return _Global_new<_Func_impl_no_alloc>(_Callee);
}
else {
return ::new (_Where) _Func_impl_no_alloc(_Callee);// 否则,需要使用placement new 操作
}
}
virtual _Mybase* _Move(void* _Where) noexcept override {
if
_CONSTEXPR_IF(_Is_large<_Func_impl_no_alloc>) {
(void) _Where;
return nullptr;
}
else {
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)...);
}
virtual const type_info& _Target_type() const noexcept override {
#if _HAS_STATIC_RTTI
return typeid(_Callable);
#else // _HAS_STATIC_RTTI
return typeid(void);
#endif // _HAS_STATIC_RTTI
}
virtual const void* _Get() const noexcept override {
return _STD addressof(_Callee);
}
virtual void _Delete_this(bool _Dealloc) noexcept override { // destroy self
this->~_Func_impl_no_alloc();
if (_Dealloc) {
_Deallocate(this, sizeof(_Func_impl_no_alloc));
}
}
_Callable _Callee;
};
既然是函数对象,那么其调用过程如何呢?
接口定义里面,定义了如下接口:
virtual _Rx _Do_call(_Types&&...) = 0;
另外我们找到了重载operator()的地方:
// CLASS TEMPLATE _Func_class --------也就是std::function的基类
template
class _Func_class : public _Arg_types<_Types...> {
public:
using result_type = _Ret;
using _Ptrt = _Func_base<_Ret, _Types...>;// 这个基类定义了一系列的虚函数
_Func_class() noexcept {
_Set(nullptr);
}
_Ret operator()(_Types... _Args) const {// _Func_class 重载了operator(),以进行函数调用
if (_Empty()) {
_Xbad_function_call();
}
const auto _Impl = _Getimpl();
return _Impl->_Do_call(_STD forward<_Types>(_Args)...);
}
_Func_impl_no_alloc 中实现如下:
virtual _Rx _Do_call(_Types&&... _Args) override { // call wrapped function
return _Invoker_ret<_Rx>::_Call(_Callee, _STD forward<_Types>(_Args)...);
}
其中用了一些奇淫技巧,如下:
最终会跑到这里的宏定义里面:
#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 \
static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept( \
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)...); \
} \
}; \
\
struct _CONCAT( \
NAME_PREFIX, _Invoker_pmf_refwrap) { /* INVOKE a pointer to member function on a reference_wrapper */ \
template \
static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept( \
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 */ \
template \
static CONSTEXPR auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args2) noexcept( \
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 a [smart] pointer */ \
return ((*_STD forward<_Ty1>(_Arg1)).*_Pmf)(_STD forward<_Types2>(_Args2)...); \
} \
}; \
\
struct _CONCAT(NAME_PREFIX, _Invoker_pmd_object) { /* INVOKE a pointer to member data on an object */ \
template \
static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept(noexcept(_STD forward<_Ty1>(_Arg1).*_Pmd)) \
-> decltype(_STD forward<_Ty1>(_Arg1).*_Pmd) { /* INVOKE a pointer to member data on an object */ \
return _STD forward<_Ty1>(_Arg1).*_Pmd; \
} \
}; \
\
struct _CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap) { /* INVOKE a pointer to member data on a reference_wrapper */ \
template \
static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept( \
noexcept(_STD forward<_Ty1>(_Arg1).get().*_Pmd)) \
-> decltype( \
_STD forward<_Ty1>(_Arg1).get().*_Pmd) { /* INVOKE a pointer to member data on a reference_wrapper */ \
return _STD forward<_Ty1>(_Arg1).get().*_Pmd; \
} \
}; \
\
struct _CONCAT(NAME_PREFIX, _Invoker_pmd_pointer) { /* INVOKE a pointer to member data on a [smart] pointer */ \
template \
static CONSTEXPR auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) noexcept( \
noexcept((*_STD forward<_Ty1>(_Arg1)).*_Pmd)) \
-> decltype( \
(*_STD forward<_Ty1>(_Arg1)).*_Pmd) { /* INVOKE a pointer to member data on a [smart] pointer */ \
return (*_STD forward<_Ty1>(_Arg1)).*_Pmd; \
} \
}; \
\
struct _CONCAT(NAME_PREFIX, _Invoker_functor) { /* INVOKE a function object */ \
template \
static CONSTEXPR auto _Call(_Callable&& _Obj, _Types&&... _Args) noexcept( \
noexcept(_STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...))) \
-> decltype( \
_STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...)) { /* INVOKE a function object */ \
return _STD forward<_Callable>(_Obj)(_STD forward<_Types>(_Args)...); \
} \
}; \
\
template , \
bool _Is_pmf = is_member_function_pointer_v<_Removed_cvref>, \
bool _Is_pmd = is_member_object_pointer_v<_Removed_cvref>> \
struct _CONCAT(NAME_PREFIX, _Invoker1); \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, true, false> \
: conditional_t::_Class_type, remove_reference_t<_Ty1>>, \
_CONCAT(NAME_PREFIX, _Invoker_pmf_object), \
conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>, \
_CONCAT(NAME_PREFIX, _Invoker_pmf_refwrap), \
_CONCAT(NAME_PREFIX, _Invoker_pmf_pointer)>> { /* pointer to member function */ \
}; \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, true> \
: conditional_t< \
is_base_of_v::_Class_type, remove_reference_t<_Ty1>>, \
_CONCAT(NAME_PREFIX, _Invoker_pmd_object), \
conditional_t<_Is_specialization_v<_Remove_cvref_t<_Ty1>, reference_wrapper>, \
_CONCAT(NAME_PREFIX, _Invoker_pmd_refwrap), \
_CONCAT(NAME_PREFIX, _Invoker_pmd_pointer)>> { /* pointer to member data */ \
}; \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1, _Removed_cvref, false, false> \
: _CONCAT(NAME_PREFIX, _Invoker_functor) { /* function object */ \
}; \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker); \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable> : _CONCAT(NAME_PREFIX, _Invoker_functor) { /* zero arguments */ \
}; \
\
template \
struct _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Ty1, _Types2...> \
: _CONCAT(NAME_PREFIX, _Invoker1)<_Callable, _Ty1> { /* one or more arguments */ \
}; \
\
template \
CONSTEXPR auto _CONCAT(NAME_PREFIX, invoke)(_Callable && _Obj, _Types && ... _Args) noexcept( \
noexcept(_CONCAT(NAME_PREFIX, _Invoker) < _Callable, \
_Types... > ::_Call(_STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...))) \
->decltype(_CONCAT(NAME_PREFIX, _Invoker) < _Callable, \
_Types... > ::_Call( \
_STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)) { /* INVOKE a callable object */ \
return _CONCAT(NAME_PREFIX, _Invoker)<_Callable, _Types...>::_Call( \
_STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...); \
}
_IMPLEMENT_INVOKE(_EMPTY_ARGUMENT, inline)
这个可读性就太差了,既然微软提供的functional 中的这部分功能,就是利用了template 的能力,理想情况下,我们是可以通过自己的封装来实现一个建议版本的functional的,看时间和精力吧,可以尝试实现一下。