轉自:
https://www.cnblogs.com/cmranger/p/4743926.html
/////////////////////
std::bind
bind是對C++98標准中函數適配器bind1st/bind2nd的泛化和增強,可以適配任意的可調用對象,包括函數指針、函數引用、成員函數指針和函數對象。bind
接受的第一個參數必須是一個可調用的對象f,可以是函數、函數指針、函數對象和成員函數指針,之后接受的參數的數量必須與f的參數數量相等,這些參數將被傳遞給f作為入參。
綁定完成后,bind會返回一個函數對象,它內部保存了f的拷貝,具有operator()
,返回值類型被自動
推導為f的返回值類型。反生調用時,這個函數對象將把之前存儲的參數轉發給f完成調用。
如:
int Add(int num1, int num2) { return (num1 + num2); } Add(1,2); //等價於一個具有無參operator()的bind函數對象調用 std::bind(&Add,1,2)();
這是bind
最簡單的形式。bind
表達式存儲了Add和參數1,2的拷貝,產生了一個臨時的函數對象。因為Add接受兩個參數,而1,2都是實參,因此臨時函數對象將具有一個無參的operator()
。當operator()
調用發生時函數對象把1、2的拷貝傳遞給Add,完成真正的調用。
bind
的真正威力在與占位符,_1 _2 _3 ...
,(為了避免與boost庫的占位符沖突,標准占位符定義在std::placeholders
名字空間,使用時:std::placeholders::_1
),占位符可以取代bind中參數的位置,在發生函數調用時才接受真正的參數。
占位符的名字表示它在調用時中的順序,而在綁定式中沒有順序要求。如下:
int Sub(int num1,int num2) { return (num1 - num2); } std::bind(&Sub,std::placeholders::_1,std::placeholders::_2)(2,1); //等價於 Sub(2,1); std::bind(&Sub,std::placeholders::_2,std::placeholders::_1)(2,1); //等價於 Sub(1,2);
bind詳細用法:
//普通全局函數 void Out( int & elem) { std::cout << elem << " "; } //類 template<typename T> class Print { public: Print(const char * prefix = "") : _prefix(prefix) , _printNum(0) { } //非靜態成員函數 void PrintElem(const T & elem) { _printNum++; if (_printNum <= 1) { cout << "\n" << _prefix << ": "; } cout << elem << " "; } //靜態成員函數 static void static_fun() { std::cout << "\nstatic func!"; } private: string _prefix; size_t _printNum; }; int arr[] = {1,2,1,3,4,8,9,8}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
//綁定普通函數 std::for_each(v.begin(),v.end(),std::bind(&Out,std::placeholders::_1)); //綁定類的非靜態成員函數 //第一個占位符的位置必須是一個類的實例、引用或指針 Print<int> print("bind member function"); std::for_each(v.begin(),v.end(), std::bind(&(Print<int>::PrintElem),&print,std::placeholders::_1)); //注:必須在成員函數前加上取地址操作符&,表明這是一個成員函數指針,否則會無法通過編譯。 //綁定靜態成員函數 與綁定全局函數沒有區別 std::function<void(void)> ff = std::bind(&Print<int>::static_fun); ff();
綁定函數對象:
bind可以綁定任意的函數對象,包括標准庫中的所有預定義的函數對象。
如果函數對象有內部類型定義result_type
,那么bind可以自動推導出返回值類型,用法與綁定普通函數一樣。否則,需要在綁定形式上做出變動,用模版參數指明返回類型。bind<result_type>(functiontor, ...)
標准庫中大部分函數對象都有result_type
定義,因此不需要特別的形式。
//綁定預定義的函數對象 std::transform(v.begin(),v.end(),v.begin(), std::bind(std::plus<int>(),std::placeholders::_1,10)); //綁定函數對象 //綁定自定義的函數對象 //要想bind 綁定自定義的函數對象,必須提供一些型別的成員來反映其參數和返回值的型別, //為了方便,可以繼承 binary_function等 template<typename T1, typename T2> struct fopow : public std::binary_function<T1,T2,T1> { T1 operator() (T1 base, T2 exp) const { return std::pow(base,exp); } }; std::transform(v.begin(),v.end(),v.begin(), std::bind(fopow<double,int>(),std::placeholders::_1,2)); //自己定義result_type template<typename T> struct MyPlus { typedef T argument_type; typedef T result_type; result_type operator() (const argument_type & arg1, const argument_type & arg2) const { return (arg1 - arg2); } }; std::function<int(int)> f = std::bind(MyPlus<int>(),std::placeholders::_1,10); std::transform(v.begin(),v.end(),v.begin(),f);
補充:
//binary_function原型 template<class _Arg1, class _Arg2, class _Result> struct binary_function { // base class for binary functions typedef _Arg1 first_argument_type; typedef _Arg2 second_argument_type; typedef _Result result_type; };