好比,有一個簡單需求:找到一個vector<string>
中,長度小於3的字符串的數目。解決方法可能會是:less
int count(const std::vector<std::string>& str_vec, const size_t threshold) { int size = 0; std::vector<std::string>::const_iterator it; for (it = str_vec.begin(); it != str_vec.end(); ++ it) { if (it->length() < threshold) { ++ size; } } return size; }
其實,數據STL的同窗應該知道有個count_if
函數。count_if
的功能就是對於某種容器,對符合條件的元素進行計數。count_if
包含三個參數,容器的開始地址、容器的結束地址、以及參數爲元素類型的函數。函數
使用count_if
的代碼能夠這樣寫:spa
bool test(const std::string& str) { return str.length() < 3; } int count(const std::vector<std::string>& str_vec) { return std::count_if(str_vec.begin(), str_vec.end(), test); }
可是,這樣有個問題:沒有擴展性。好比,判斷的字符串由長度3變成5呢?將test
函數上面再增長一個長度參數能夠嗎?不行,count_if
的實現就決定了test
必須是單一參數的。既想知足count_if
的語法要求,又須要讓判斷的函數具備可擴展性,這時候就須要functor
了。code
functor
登場functor
的含義是:調用它就像調用一個普通的函數同樣,不過它的本質是一個類的實例的成員函數(operator()
這個函數),因此functor
也叫function object
。
所以如下代碼的最後兩個語句是等價的:three
class SomeFunctor { public: void operator() (const string& str) { cout << "Hello " << str << end; } }; SomeFunctor functor; functor("world"); //Hello world functor.operator()("world"); //Hello world
其實,它並不算是STL中的一部分,不過須要STL中的函數都把functor
所謂參數之一,functor
起到了定製化的做用。functor
與其它普通的函數相比,有一個明顯的特色:可使用成員變量。這樣,就提供了擴展性。字符串
繼續上面例子,寫成functor
的形式:get
class LessThan { public: LessThan(size_t threshold): _threshold(threshold) {} bool operator() (const std::string str) { return str.length() < _threshold; } private: const size_t _threshold; }; int count(const std::vector<std::string>& str_vec) { LessThan less_than_three(3); return std::count_if(str_vec.begin(), str_vec.end(), less_than_three); //LessThan less_than_five(5); //std::count_if(str_vec.begin(), str_vec.end(), less_than_five); } int count_v2(const std::vector<std::string>& str_vec, const size_t threshold) { return std::count_if(str_vec.begin(), str_vec.end(), LessThan(threshold)); }
有人可能會說,我已經有了本身實現的判斷函數了,可是直接用又不行,有啥解決辦法嗎?
實際上是有的!(我也是最近才發現的)string
C++11的標準中,提供了一套函數,能將一個普通的、不符合使用方要求的函數,轉變成一個符合參數列表要求的functor
,這實在是太酷了!it
好比用戶本身實現的int test(const std::string& str_vec, const size_t threshold)
函數,若是能將第二個參數進行綁定,不就符合count_if
的要求了嗎?io
新標準的C++就提供了這樣一個函數——bind
。
經過std::bind
以及std::placeholders
,就能夠實現轉化,樣例代碼以下:
bool less_than_func(const std::string& str, const size_t threshold) { return str.length() < threshold; } //提供 _1 佔位符 using namespace std::placeholders; //綁定less_than_func第二個參數爲5, 轉化爲functor auto less_than_functor = std::bind(less_than_func, _1, 5); std::cout << std::count_if(str_vec.begin(), str_vec.end(), less_than_functor) << std::endl;
--EOF--