c++11中增加了std::function和std::bind,可更加方便的使用標准庫,同時也可方便的進行延時求值。
可調用對象
c++中的可調用對象存在以下幾類:
(1)函數指針
(2)具有operator()成員函數的類對象(仿函數)
(3)可被轉換為函數指針的類對象
(4)類成員(函數)指針
void func(void){ //.... } struct Foo{ void operator()(void){ //... } }; struct Bar{ using fr_t = void(*)(void); static void func(void){ //... } operator fr_t(void){ //可以進行隱式轉換,轉換結果為 fr_t 為一個函數指針 return func; //operator xxx (void) 函數可以對類的對象進行隱式轉換 } }; struct A{ int a_; void mem_func(void){ //... } }; int main(){ void(* func_ptr)(void) = &func; //1.函數指針 func_ptr(); Foo foo; //2. 仿函數 foo(); Bar bar; bar(); //可被轉化為函數指針的類對象 void (A::*mem_func_ptr)(void) = &A::mem_func; //類成員函數指針 int A::*mem_obj_ptr = &A::a; //類成員指針 return 0; }
可調用對象包裝器——std::function
c++11通過std::function, std::bind統一了可調用對象的各種操作。std::function是可調用對象的包裝器,它是一個類模板,可以容納類成員(函數)指針之外的所有可調用對象。通過指定它的模板參數,它可以用統一的方式處理函數、函數對象、函數指針,並允許保存和延時執行它們。 std::function<返回值(參數類型)> f;
void func(void){ } class Foo{ public: static int foo_func(int a){ std::cout << "hello" <<std::endl; return a; } }; int main(){ std::function<void(void)> f; f = func; std::function<int(int)> = Foo::foo_func; return 0; }
std::bind綁定器
std::bind用來將可調用對象與其參數一起進行綁定。綁定后的結果可以使用 std::function進行保存,並延遲調用到任何我們需要的時候。它主要有兩大作用:
(1)將可調用對象與其參數一起綁定成一個仿函數
(2)將多元(參數個數為n>1)可調用對象轉成x元( 0 <= 0 <= n)元可調用對象,即只綁定部分參數。
(3)使用bind可以將類的非靜態成員函數綁定起來,賦值給一個可執行std::function對象
#include<functional> using namespace std; int func(int a, int b){ std::cout << "a = " << a << ", b = " << b << std::endl; return a + b; } class A{ public: int mem_func(int a, int b){ std::cout << "a = " << a << ", b = " << b << std::endl; return a + b; } }; int main(){ //直接生成一個可調用對象,然后調用,參數為3 //bind(func, 1, std::placeholders::_1)中表示將參數1 和參數 std::placeholders::_1作為函數func的參數,綁定成另一個可執行對象。 //在綁定的時候, 按照順序,1 作為 func(int a, int b) 中形參a的實參; std::placeholders::_1 作為 func(int a, int b) 中形參b的實參 //std::placeholders::_1 是占位符,表示將綁定后得到的可執行對象進行調用的時候,實參的第1個,放到 std::placeholders::_1的位置上去 //依次,std::placeholders::_2 將調用的時候實參的第2個,放到該位置上去 //注意,占位符 std::placeholders::_x 中x必須小於等於調用的時候實際參數的個數!! std::bind(func, 1, std::placeholders::_1)(3); //輸出 a = 1, b = 3 std::bind(func, 1, std::placeholders::_2)(3, 6); //輸出 a = 1, b = 6 //用function可調用對象f保存bind后的結果 std::function<int(int)> f = std::bind(func, 1, std::placeholders::_1); f(2); //輸出 a = 1, b = 2 f = std::bind(func, std::placeholders::_1, 1); f(3); //輸出 a = 3, b = 1 //將類的非靜態成員函數,以及類的對象實例,進行綁定 A a; f = std::bind(&A::mem_func, a, 1, std::placeholders::_1); f(10); return 0; }
使用組合bind函數
bind可以組合多個函數,假設要找出集合中大於5小於10的元素個數.
判斷一個數是否大於5的閉包,代碼std::bind(std::greater< int>(), std::placeholders::_1, 5)
判斷一個數是否小於10的閉包,代碼std::bind(std::less_equal< int>(), std::placeholders::_1, 10)
然后進行組合,得到:
using std::placeholders::_1; //查找集合中大於5小於等於10的元素個數 auto f = std::bind( std::logic_and<bool>(), std::bind(std::greater<int>(), _1, 5), std::bind(std::less_equal<int>(), _1, 10)); int count = std::count_if(coll.begin(), coll.end(), f);