function 원본 분석 3--c++11 function 원본 분석
9335 단어 기능 원본 분석
우선 함수 바늘이 어떻게 저장되는지 봅시다.
class _Undefined_class;// class
union _Nocopy_types{
void* _M_object;//function object
const void* _M_const_object;//const function object
void(*_M_function_pointer)();//
void (_Undefined_class::*_M_member_pointer)();//
};
union _Any_data{
void* _M_access() { return &_M_pod_data[0]; }
const void* _M_access() const { return &_M_pod_data[0]; }
template
_Tp& _M_access(){
return *static_cast<_tp>(_M_access());
}
template
const _Tp& _M_access() const{
return *static_cast(_M_access());
}
_Nocopy_types _M_unused;
char _M_pod_data[sizeof(_Nocopy_types)];
};
boost의 실현 기법과 약간 비슷하다. 재미있는 것은 유니온이 약간 비슷하다는 것이다. A union can have member functions(including constructors and destructors),but not virtual(10.3) functions._Any_데이터의 크기는 x86에서 4바이트일 것입니다.다음은 function_base, 형식 정의에서 볼 수 있듯이 포인터를 저장하기 위한
enum _Manager_operation
{
__get_type_info,
__get_functor_ptr,
__clone_functor,
__destroy_functor
};
/// Base class of all polymorphic function object wrappers.
class _Function_base
{
public:
static const std::size_t _M_max_size = sizeof(_Nocopy_types);
static const std::size_t _M_max_align = __alignof__(_Nocopy_types);
...
_Function_base() : _M_manager(nullptr) { }
~_Function_base()
{
if (_M_manager)
_M_manager(_M_functor, _M_functor, __destroy_functor);
}
bool _M_empty() const { return !_M_manager; }
typedef bool(*_Manager_type)(_Any_data&, const _Any_data&,
_Manager_operation);
_Any_data _M_functor;//function buffer
_Manager_type _M_manager;//manager
};
다음은 관리자를 보겠습니다. boost의 실현 메커니즘과 마찬가지로 이 유형은_Function_베이스에서 정의한 장점은 물건을 함께 놓는 것이다.다른 명명 공간이 아니라 boost보다 empty의 판단이 많다
template
class _Base_manager
{
protected:
static const bool __stored_locally =
(__is_location_invariant<_functor>::value
&& sizeof(_Functor) <= _M_max_size
&& __alignof__(_Functor) <= _M_max_align
&& (_M_max_align % __alignof__(_Functor) == 0));
typedef integral_constant _Local_storage;
// Retrieve a pointer to the function object
static _Functor* _M_get_pointer(const _Any_data& __source)
{
const _Functor* __ptr =
__stored_locally ? std::__addressof(__source._M_access<_functor>())
/* have stored a pointer */ : __source._M_access<_functor>();
return const_cast<_functor>(__ptr);
}
// Clone a location-invariant function object that fits within
// an _Any_data structure.
static void _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
{
new (__dest._M_access()) _Functor(__source._M_access<_functor>());
}
// Clone a function object that is not location-invariant or
// that cannot fit into an _Any_data structure.
static void _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
{
__dest._M_access<_functor>() = new _Functor(*__source._M_access<_functor>());
}
// Destroying a location-invariant object may still require
// destruction.
static void _M_destroy(_Any_data& __victim, true_type)
{
__victim._M_access<_functor>().~_Functor();
}
// Destroying an object located on the heap.
static void _M_destroy(_Any_data& __victim, false_type)
{
delete __victim._M_access<_functor>();
}
public:
// Manager
static bool _M_manager(_Any_data& __dest, const _Any_data& __source,
_Manager_operation __op)
{
switch (__op)
{
case __get_type_info:
__dest._M_access() = &typeid(_Functor);
break;
case __get_functor_ptr:
__dest._M_access<_functor>() = _M_get_pointer(__source);
break;
case __clone_functor:
_M_clone(__dest, __source, _Local_storage());
break;
case __destroy_functor:
_M_destroy(__dest, _Local_storage());
break;
}
return false;
}
static void _M_init_functor(_Any_data& __functor, _Functor&& __f)
{
_M_init_functor(__functor, std::move(__f), _Local_storage());
}
template
static bool _M_not_empty_function(const function<_signature>& __f)
{
return static_cast(__f);
}
template
static bool _M_not_empty_function(_Tp* const& __fp)
{
return __fp;
}
template
static bool _M_not_empty_function(_Tp _Class::* const& __mp)
{
return __mp;
}
template
static bool _M_not_empty_function(const _Tp&)
{
return true;
}
private:
static void _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
{
new (__functor._M_access()) _Functor(std::move(__f));
}
static void _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
{
__functor._M_access<_functor>() = new _Functor(std::move(__f));
}
};
먼저_Maybe_unary_or_binary_function, 이것은 주로 원래 표준의 unay_를 호환하기 위한 것이다function,binary_function, /**
* Derives from @c unary_function or @c binary_function, or perhaps
* nothing, depending on the number of arguments provided. The
* primary template is the basis case, which derives nothing.
*/
template
struct _Maybe_unary_or_binary_function { };
/// Derives from @c unary_function, as appropriate.
template
struct _Maybe_unary_or_binary_function<_res _t1="">
: std::unary_function<_t1 _res=""> { };
/// Derives from @c binary_function, as appropriate.
template
struct _Maybe_unary_or_binary_function<_res _t1="" _t2="">
: std::binary_function<_t1 _t2="" _res=""> { };
이어서 function 자체.template
using _Requires = typename enable_if<:value _tp="">::type;
template
class function<_res>
: public _Maybe_unary_or_binary_function<_res _argtypes...="">,
private _Function_base
{
typedef _Res _Signature_type(_ArgTypes...);
template::type>
struct _Callable : __check_func_return_type<_res2 _res=""> { };
// Used so the return type convertibility checks aren't done when
// performing overload resolution for copy construction/assignment.
template
struct _Callable : false_type { };
template
using _Requires = typename enable_if<:value _tp="">::type;
public:
typedef _Res result_type;
_Res operator()(_ArgTypes... __args) const
{
if (_M_empty())
__throw_bad_function_call();
return _M_invoker(_M_functor, std::forward<_argtypes>(__args)...);
}
bool _M_empty() const {
return !_M_manager;
}
//c++11 safe bool
explicit operator bool() const noexcept
{
return !_M_empty();
}
template>, void>,
typename = _Requires<_callable>, void>>
function(_Functor);
private:
using _Invoker_type = _Res(*)(const _Any_data&, _ArgTypes&&...);
_Invoker_type _M_invoker;
};
그리고 이 invoke_.type입니다. 이 유형은 비교적 많습니다. 일일이 전개하지 않고 하나만 선택하십시오.template
class _Function_handler;
template
class _Function_handler<_res _functor="">
: public _Function_base::_Base_manager<_functor>
{
typedef _Function_base::_Base_manager<_functor> _Base;
public:
static _Res _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
{
return (*_Base::_M_get_pointer(__functor))(
std::forward<_argtypes>(__args)...);
}
};
그리고 invoke와 mannage에 값을 부여합니다. template
template
function<_res>::
function(_Functor __f)
: _Function_base()
{
typedef _Function_handler<_signature_type _functor=""> _My_handler;
if (_My_handler::_M_not_empty_function(__f))
{
_My_handler::_M_init_functor(_M_functor, std::move(__f));
_M_invoker = &_My_handler::_M_invoke;
_M_manager = &_My_handler::_M_manager;
}
}
주의할 점은 바로 Variadic Template의 문법입니다.