function 원본 분석 3--c++11 function 원본 분석

9335 단어 기능 원본 분석
내가 분석한 것은 gcc의function 원본이다.
우선 함수 바늘이 어떻게 저장되는지 봅시다.
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의 문법입니다.

좋은 웹페이지 즐겨찾기