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);
