我在之前的隨筆中介紹了function如何保存參數,如何實現調用相關知識。對於一個函數對象或者函數指針來說,應該很容易理解。不過對於如何在function中保存類的成員函數,這個還是值得一說的。 還是按照之前的方式,通過boost的type_index,我們可以比較容易的知道function的父類是 ...
我在之前的隨筆中介紹了function如何保存參數,如何實現調用相關知識。對於一個函數對象或者函數指針來說,應該很容易理解。不過對於如何在function中保存類的成員函數,這個還是值得一說的。
還是按照之前的方式,通過boost的type_index,我們可以比較容易的知道function的父類是_Func_class。
這裡先看一段代碼:
template<class _Fx, class _Inv_res = typename _Mybase::template _Result_of_invoking_t<_Fx&>, class = typename _Mybase::template _Enable_if_returnable_t<_Inv_res> > function(_Fx _Func) { // construct wrapper holding copy of _Func this->_Reset(_STD move(_Func)); }
這個是function的一個構造函數,其中的_Inv_res是這個構造函數能夠使用的條件,條件的內容是_Mybase::_Result_of_invoking_t<_Fx&>可以獲得一個類型。
現在我們查看_Result_of_invoking_t定義的位置:
protected: template<class _Fx> using _Result_of_invoking_t = result_of_t<_Fx(_Types...)>;
上面是在_Func_class中的定義。下麵給出類result_of_t的定義。
template<class _Ty> using result_of_t = typename result_of<_Ty>::type; template<class _Void, class... _Types> struct _Result_of { // selected when _Fty isn't callable with _Args }; template<class... _Types> struct _Result_of< void_t< _Unique_tag_result_of, // TRANSITION, C1XX decltype(_STD invoke(_STD declval<_Types>()...))>, _Types...> { // selected when _Fty is callable with _Args typedef decltype(_STD invoke(_STD declval<_Types>()...)) type; }; template<class _Fty> struct result_of { // explain usage static_assert(_Always_false<_Fty>::value, "result_of<CallableType> is invalid; use " "result_of<CallableType(zero or more argument types)> instead."); }; #define _RESULT_OF(CALL_OPT, X1, X2) \ template<class _Fty, \ class... _Args> \ struct result_of<_Fty CALL_OPT (_Args...)> \ : _Result_of<void, _Fty, _Args...> \ { /* template to determine result of call operation */ \ };
由上述代碼可知,result_of的實現依賴於std::invoke函數的實現。
我們再查看一下function函數的調用路徑:
_Ret operator()(_Types... _Args) const { // call through stored object if (_Empty()) _Xbad_function_call(); return (_Getimpl()->_Do_call(_STD forward<_Types>(_Args)...)); }
上述是_Func_class的調用函數。
virtual _Rx _Do_call(_Types&&... _Args) { // call wrapped function return (_Invoke_ret(_Forced<_Rx>(), _Callee(), _STD forward<_Types>(_Args)...)); }
這個是_Func_impl的調用,也就是上面_Getimpl()->_Do_call的實現函數。下麵,我們再查看一下_Invoke_ret的實現:
template<class _Cv_void, class... _Valtys> inline void _Invoke_ret(_Forced<_Cv_void, true>, _Valtys&&... _Vals) { // INVOKE, "implicitly" converted to void _STD invoke(_STD forward<_Valtys>(_Vals)...); } template<class _Rx, class... _Valtys> inline _Rx _Invoke_ret(_Forced<_Rx, false>, _Valtys&&... _Vals) { // INVOKE, implicitly converted to _Rx return (_STD invoke(_STD forward<_Valtys>(_Vals)...)); } template<class... _Valtys> inline auto _Invoke_ret(_Forced<_Unforced, false>, _Valtys&&... _Vals) -> decltype(_STD invoke(_STD forward<_Valtys>(_Vals)...)) { // INVOKE, unchanged return (_STD invoke(_STD forward<_Valtys>(_Vals)...)); }
由上面代碼可見,無一例外,function的判斷和實現都依賴於std::invoke的實現。那麼std::invoke是如何實現的呢?
template<class _Callable, class... _Types> inline auto invoke(_Callable&& _Obj, _Types&&... _Args) -> decltype(_Invoker<_Callable, _Types...>::_Call( _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)) { // INVOKE a callable object return (_Invoker<_Callable, _Types...>::_Call( _STD forward<_Callable>(_Obj), _STD forward<_Types>(_Args)...)); }
在VS2015中,invoke的實現代碼如上,可見invoke的實現依賴於_Invoker類。下麵,我們查看一下_Invoker的實現:
template<class _Callable, class... _Types> struct _Invoker; template<class _Callable> struct _Invoker<_Callable> : _Invoker_functor { // zero arguments }; template<class _Callable, class _Ty1, class... _Types2> struct _Invoker<_Callable, _Ty1, _Types2...> : _Invoker1<_Callable, _Ty1> { // one or more arguments };
可見,我們需要繼續查看_Invoker1的實現:
template<class _Callable, class _Ty1, class _Decayed = typename decay<_Callable>::type, bool _Is_pmf = is_member_function_pointer<_Decayed>::value, bool _Is_pmd = is_member_object_pointer<_Decayed>::value> struct _Invoker1; template<class _Callable, class _Ty1, class _Decayed> struct _Invoker1<_Callable, _Ty1, _Decayed, true, false> : _If<is_base_of< typename _Is_memfunptr<_Decayed>::_Class_type, typename decay<_Ty1>::type>::value, _Invoker_pmf_object, _Invoker_pmf_pointer>::type { // pointer to member function }; template<class _Callable, class _Ty1, class _Decayed> struct _Invoker1<_Callable, _Ty1, _Decayed, false, true> : _If<is_base_of< typename _Is_member_object_pointer<_Decayed>::_Class_type, typename decay<_Ty1>::type>::value, _Invoker_pmd_object, _Invoker_pmd_pointer>::type { // pointer to member data }; template<class _Callable, class _Ty1, class _Decayed> struct _Invoker1<_Callable, _Ty1, _Decayed, false, false> : _Invoker_functor { // function object };
以及實現_Invoker1的底層類:
struct _Invoker_pmf_object { // INVOKE a pointer to member function on an object template <class _Decayed, class _Ty1, class... _Types2> static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... _Args) ->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 _Invoker_pmf_pointer { // INVOKE a pointer to member function on a [smart] pointer template <class _Decayed, class _Ty1, class... _Types2> static auto _Call(_Decayed _Pmf, _Ty1&& _Arg1, _Types2&&... Args2) ->decltype(((*std::forward<_Ty1>(_Arg1)).*_Pmf)( std::forward<_Types2>(_Arg2)...)) { // INVOKE a pointer to member function on a [smart] pointer return (((*std::forward<_Ty1>(_Arg1)).*_Pmf)( std::forward<_Types2>(_Arg2)...)); } }; struct _Invoker_pmd_object { // INVOKE a pointer to member data on an object template<class _Decayed, class _Ty1> static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) ->decltype(std::forward<_Ty1>(_Arg1).*_Pmd) { // INVOKE a pointer to member data on a [smart] pointer return (std::forward<_Ty1>(_Arg1).*_Pmd); } }; struct _Invoker_pmd_pointer { // INVOKE a pointer to member data on a [smart] pointer template <class _Decayed, class _Ty1> static auto _Call(_Decayed _Pmd, _Ty1&& _Arg1) ->decltype((*std::forward<_Ty1>(_Arg1)).*_Pmd) { // INVOKE a pointer to member data on a [smart] pointer return ((*std::forward<_Ty1>(_Arg1)).*_Pmd); } }; struct _Invoker_functor { // INVOKE a function object template <class _Callable, class... _Types> static auto _Call(_Callable&& _Obj, _Types&&... _Args) ->decltype(std::forward<_Callable>(_Obj)( std::forward<_Types>(_Args)...)) { // INVOKE a function object return (std::forward<_Callable>(_Obj)( std::forward<_Types>(_Args)...)); } };
實現的過程,主要在於:bool _Is_pmf = is_member_function_pointer<_Decayed>::value和bool _Is_pmd = is_member_object_pointer<_Decayed>::value>兩個判斷語句,通過這個來實現SFINAE的語義,從而實現針對類型的特例化。為了說明上面兩個判斷才是重點,輸入如下代碼:
class A { public: A(){} void printA() const { std::cout << "printA" << std::endl; } }; void printB(A a) { std::cout << "printB" << std::endl; } int main() { std::_Invoker_pmf_object::_Call(&A::printA, A()); std::_Invoker_pmf_pointer::_Call(&A::printA, &A()); std::_Invoker_functor::_Call(printB, A()); return 0; }
查看列印結果。由於_Invoker_pmf_object,_Invoker_pmf_pointer和_Invoker_functor的實現本來很簡單,所以invoke調用的重點在於上述判斷語句。這裡就解釋到此,時間倉促,希望見諒。