Effective C++: std::bind特性/std::bind實現.

1, 小特性linux

demo1:ios

#include <iostream>
#include <functional>

void function(int& number)
{
	number = 50;
}

using functionType = void(*)(int&);

int main()
{
	//case 1:
	int n1 = 10;
	auto f1 = std::bind(function, 10);
	f1();
	std::cout<<n1<<std::endl; //輸出: 10.
	
	//case 2:
	int n2 = 20;
	auto f2 = std::bind(function, std::ref(n2));
	f2();
	std::cout<<n2<<std::endl; //輸出: 50. 
	
	//case 3:
	int n3 = 30;
	auto f3 = std::bind(function, n3);
	f3();
	std::cout<< n3 <<std::endl; //輸出: 30 
	
	
	return 0;
}

 

 

2, std::bind的實現(debian GCC6.3)socket

 因爲標準沒用要求std::bind的具體實現只是要求了std::bind的具體功能.我這裏只有linux. vs就不考慮了.下面讓咱們一點一點往下看.函數

 

code block 1: std::bindspa

template<typename _Func, typename... _BoundArgs>
    inline typename
    _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
    bind(_Func&& __f, _BoundArgs&&... __args)
    {
      typedef _Bind_helper<false, _Func, _BoundArgs...> __helper_type;
      typedef typename __helper_type::__maybe_type __maybe_type;
      typedef typename __helper_type::type __result_type;
      return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)),
			   std::forward<_BoundArgs>(__args)...);
    }

  1), 首先咱們看到 std::bind(__Func&& f,  _BoundArgs&&... __args).指針

 2), 雖然f的類型爲: __Func&&可是仍然是能夠傳遞一個指向class/struct member function/data的指針.code

3), 咱們看到std::bind依賴 _Bind_helper(struct)以及 __is_socketlike(struct).ci

 

code block 2:  __is_socketlikeget

template<typename _Tp, typename _Tp2 = typename decay<_Tp>::type>
    using __is_socketlike = __or_<is_integral<_Tp2>, is_enum<_Tp2>>;

1) __is_socketlike依賴 __or_(struct), 同時接受一個2個template argument:it

                _Tp 和  _Tp2, 可是__or_(struct)並不依賴_Tp, 而是是須要獲取 std::decay<_Tp>::type獲得的_Tp2.

 

code block 3: __or_   和  conditional

template<typename...>
    struct __or_; //struct template declare


  template<>
    struct __or_<>
    : public false_type
    { };   //specialized


  template<typename _B1>
    struct __or_<_B1>
    : public _B1
    { };  //specialized

  template<typename _B1, typename _B2>
    struct __or_<_B1, _B2>
    : public conditional<_B1::value, _B1, _B2>::type
    { }; //specialized

  template<typename _B1, typename _B2, typename _B3, typename... _Bn>
    struct __or_<_B1, _B2, _B3, _Bn...>
    : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type
    { }; //specialized




  template<bool _Cond, typename _Iftrue, typename _Iffalse>
    struct conditional
    { typedef _Iftrue type; }; // struct template declare
 

  template<typename _Iftrue, typename _Iffalse>
    struct conditional<false, _Iftrue, _Iffalse>
   { typedef _Iffalse type; }; // specialized

 1),  首先看  conditional(struct):

       1, 當 _Cond爲true的時候, conditional的類型爲 _Iftrue

      2, 當_Cond爲false的時候, conditional的類型爲 _Iffalse

2), __or_(struct)能夠接受 可變的template arguments, 可是須要注意的是咱們提供的 template arguments必須是能夠 operator bool 且必須具備一個 member data  value 且value必須是bool類型.

 

 

code block 4:  _Bind_helper

template<bool _SocketLike, typename _Func, typename... _BoundArgs>
    struct _Bind_helper
    : _Bind_check_arity<typename decay<_Func>::type, _BoundArgs...>
    {
      typedef _Maybe_wrap_member_pointer<typename decay<_Func>::type>
	__maybe_type;
      typedef typename __maybe_type::type __func_type;
      typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type;
    }; //struct template declare



  template<typename _Func, typename... _BoundArgs>
    struct _Bind_helper<true, _Func, _BoundArgs...>
    { }; //specialized

1),若是 _Sokectlike的值爲true, 就代表 _Func的類型爲 integer/enum, 這個時候是不能做爲函數調用的所以錯誤.

2),  _Bind_helper依賴 _Bind_check_arity(struct), _Maybe_wrap_member_pointer(struct) 以及 _Bind(struct).

 

code block 5: _Bind_check_arity

template<typename _Func, typename... _BoundArgs>
    struct _Bind_check_arity { };

  template<typename _Ret, typename... _Args, typename... _BoundArgs>
    struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...>
    {
      static_assert(sizeof...(_BoundArgs) == sizeof...(_Args),
                   "Wrong number of arguments for function");
    };

  template<typename _Ret, typename... _Args, typename... _BoundArgs>
    struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...>
    {
      static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args),
                   "Wrong number of arguments for function");
    };

  template<typename _Tp, typename _Class, typename... _BoundArgs>
    struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...>
    {
      using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity;
      using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs;
      static_assert(_Varargs::value
		    ? sizeof...(_BoundArgs) >= _Arity::value + 1
		    : sizeof...(_BoundArgs) == _Arity::value + 1,
		    "Wrong number of arguments for pointer-to-member");
    };
相關文章
相關標籤/搜索