- 函數對象:具有函數性質的對象
- 使得用戶像使用函數一樣使用它
- 一般函數提供兩個版本,第一個版本使用operator < ;第二版本需要用戶 指定某種操作
- 第二版本就是設計一個函數,將函數指針作為算法的一個參數;或者將函數操作設計成為一個仿函數,就語言層面是一個class,再以該仿函數產生一個對象,并以此對象作為算法的一個參數
- 函數指針就可以完成任務,為啥需要引入 函數對象呢?因為函數指針無法滿足STL對抽象性的要求,也無法適配STL的其余組件(適配器)搭配,產生靈活的變化
- 仿函數就是行為類似函數的對象,為了實現這個功能點,其類別定義中必須自定義(改寫或者重載)function call運算子(operator() ),這樣就可以在函數的對象后面加上一對小括號,以此來調用函數所定義的 operator()?
?分類
- 操作個數:一元、二元
- 功能劃分:算法運算、關系運算、邏輯運算
unary_function
- 用于呈現一元函數的參數型別 和 返回值的型別
//STL規定 每一個Adaptable Unary Function都應該繼承這個型別
template <class Arg,class Result>
struct unary_function{typedef Arg argument_type;typedef Result result_type;
};
- 某一個仿函數繼承了?unary_function ,其用戶便可以獲取這個仿函數的參數型別
//以下函數繼承了unary_function
template <class T>
struct negate : public unary_function<T,T>{T operator()(const T& x)const {return -x;}
};//以下配接器(adapter) 用來表示某個仿函數的邏輯
template <class Predicate>
class ungry_negate{
public:bool operator()(const typename Predicate::argument_type& x)const{}
};
?binary_function
- 用于呈現二元函數的第一參數型別、第二參數型別和返回數值型別
//STL規定 每一個Adaptable Binary Function都應該繼承這個型別
template <class Arg1,class Arg2,class Result>
struct binary_function{typedef Arg1 first_argument_type;typedef Arg2 second_argument_type;typedef Result result_type;
};//以下函數繼承了unary_function
template <class T>
struct plus : public binary_function<T,T,T>{T operator()(const T& x,const T&y)const {return x+y;}
};//以下配接器(adapter) 用來將某個二元函數轉化為一元函數
template <class Operation>
class binder1st{
protected:Operation op;typedef typename Operation::first_argument_type value;
public:typename Operation::result_type operator()(const typename Operation::second_argument_type& x)const{}
};
算數類仿函數
- 加法、減法、乘法、除法、模(余數)、否
- 除了否是一元函數,其余的都是二元函數
- 加法? plus<T>
template <class T> struct plus {T operator() (const T& x, const T& y) const {return x+y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// plus example
#include <iostream> // std::cout
#include <functional> // std::plus
#include <algorithm> // std::transformint main () {int first[]={1,2,3,4,5};int second[]={10,20,30,40,50};int results[5];std::transform (first, first+5, second, results, std::plus<int>());for (int i=0; i<5; i++)std::cout << results[i] << ' ';std::cout << '\n';return 0;
}
- 減法? minus<T>
template <class T> struct minus {T operator() (const T& x, const T& y) const {return x-y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// minus example
#include <iostream> // std::cout
#include <functional> // std::minus
#include <algorithm> // std::transformint main () {int numbers[]={10,20,30};int result;result = std::accumulate (numbers, numbers+3, 100, std::minus<int>());std::cout << "The result of 100-10-20-30 is " << result << ".\n";return 0;
}
- 乘法? multiplies<T>
template <class T> struct multiplies {T operator() (const T& x, const T& y) const {return x*y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// factorials (multiplies example)
#include <iostream> // std::cout
#include <functional> // std::multiplies
#include <numeric> // std::partial_sumint main () {int numbers[9];int factorials[9];for (int i=0;i<9;i++) numbers[i]=i+1;std::partial_sum (numbers, numbers+9, factorials, std::multiplies<int>());for (int i=0; i<9; i++)std::cout << numbers[i] << "! is " << factorials[i] << '\n';return 0;
}Edit & Run
- 除法? divides<T>
template <class T> struct divides {T operator() (const T& x, const T& y) const {return x/y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// divides example
#include <iostream> // std::cout
#include <functional> // std::divides
#include <algorithm> // std::transformint main () {int first[]={10,40,90,40,10};int second[]={1,2,3,4,5};int results[5];std::transform (first, first+5, second, results, std::divides<int>());for (int i=0; i<5; i++)std::cout << results[i] << ' ';std::cout << '\n';return 0;
}
- 模(余數)? modules<T>
template <class T> struct modulus {T operator() (const T& x, const T& y) const {return x%y;}typedef T first_argument_type;typedef T second_argument_type;typedef T result_type;
};
// modulus example
#include <iostream> // std::cout
#include <functional> // std::modulus, std::bind2nd
#include <algorithm> // std::transformint main () {int numbers[]={1,2,3,4,5};int remainders[5];std::transform (numbers, numbers+5, remainders, std::bind2nd(std::modulus<int>(),2));for (int i=0; i<5; i++)std::cout << numbers[i] << " is " << (remainders[i]==0?"even":"odd") << '\n';return 0;
}
- 否? negate<T>
template <class T> struct negate {T operator() (const T& x) const {return -x;}typedef T argument_type;typedef T result_type;
};
// negate example
#include <iostream> // std::cout
#include <functional> // std::negate
#include <algorithm> // std::transformint main () {int numbers[]={10,-20,30,-40,50};std::transform (numbers, numbers+5, numbers, std::negate<int>());for (int i=0; i<5; i++)std::cout << numbers[i] << ' ';std::cout << '\n';return 0;
}
- 可以創建一個指定類型的對象或者產生一個無名的臨時對象來履行對應的函數的功能
證同元素
- ?即數值A如果和該元素做op運算,會得到A自己
- 加法的證同元素為0,因為任何元素加上0仍然是他自己
- 乘法的證同元素是1 ,因為任何元素乘以1仍然是他自己
關系運算類仿函數
- ?等于 equal_to<T>
template <class T> struct equal_to {bool operator() (const T& x, const T& y) const {return x==y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// equal_to example
#include <iostream> // std::cout
#include <utility> // std::pair
#include <functional> // std::equal_to
#include <algorithm> // std::mismatchint main () {std::pair<int*,int*> ptiter;int foo[]={10,20,30,40,50};int bar[]={10,20,40,80,160};ptiter = std::mismatch (foo, foo+5, bar, std::equal_to<int>());std::cout << "First mismatching pair is: " << *ptiter.first;std::cout << " and " << *ptiter.second << '\n';return 0;
}
- 不等于 not_equal_to<T>
template <class T> struct not_equal_to {bool operator() (const T& x, const T& y) const {return x!=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// not_equal_to example
#include <iostream> // std::cout
#include <functional> // std::not_equal_to
#include <algorithm> // std::adjacent_findint main () {int numbers[]={10,10,10,20,20};int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>()) +1;std::cout << "The first different element is " << *pt << '\n';return 0;
}
- 大于 greater<T>
template <class T> struct greater {bool operator() (const T& x, const T& y) const {return x>y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// greater example
#include <iostream> // std::cout
#include <functional> // std::greater
#include <algorithm> // std::sortint main () {int numbers[]={20,40,50,10,30};std::sort (numbers, numbers+5, std::greater<int>());for (int i=0; i<5; i++)std::cout << numbers[i] << ' ';std::cout << '\n';return 0;
}
- 大于等于 greater_equal<T>
template <class T> struct greater_equal {bool operator() (const T& x, const T& y) const {return x>=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// greater_equal example
#include <iostream> // std::cout
#include <functional> // std::greater_equal, std::bind2nd
#include <algorithm> // std::count_ifint main () {int numbers[]={20,-30,10,-40,0};int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::greater_equal<int>(),0));std::cout << "There are " << cx << " non-negative elements.\n";return 0;
}
- 小于 less<T>
template <class T> struct less {bool operator() (const T& x, const T& y) const {return x<y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// less example
#include <iostream> // std::cout
#include <functional> // std::less
#include <algorithm> // std::sort, std::includesint main () {int foo[]={10,20,5,15,25};int bar[]={15,10,20};std::sort (foo, foo+5, std::less<int>()); // 5 10 15 20 25std::sort (bar, bar+3, std::less<int>()); // 10 15 20if (std::includes (foo, foo+5, bar, bar+3, std::less<int>()))std::cout << "foo includes bar.\n";return 0;
}
- 小于等于 less_equal<T>
template <class T> struct less_equal {bool operator() (const T& x, const T& y) const {return x<=y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// less_equal example
#include <iostream> // std::cout
#include <functional> // std::less_equal, std::bind2nd
#include <algorithm> // std::count_ifint main () {int numbers[]={25,50,75,100,125};int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::less_equal<int>(),100));std::cout << "There are " << cx << " elements lower than or equal to 100.\n";return 0;
}
邏輯運算類仿函數
- ?and or Not?
- and 和 or是二元運算符號 Not是一元符號
- and? logic_and<T>
template <class T> struct logical_and {bool operator() (const T& x, const T& y) const {return x&&y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// logical_and example
#include <iostream> // std::cout, std::boolalpha
#include <functional> // std::logical_and
#include <algorithm> // std::transformint main () {bool foo[] = {true,false,true,false};bool bar[] = {true,true,false,false};bool result[4];std::transform (foo, foo+4, bar, result, std::logical_and<bool>());std::cout << std::boolalpha << "Logical AND:\n";for (int i=0; i<4; i++)std::cout << foo[i] << " AND " << bar[i] << " = " << result[i] << "\n";return 0;
}
- or? ? logic_or<T>
template <class T> struct logical_or {bool operator() (const T& x, const T& y) const {return x||y;}typedef T first_argument_type;typedef T second_argument_type;typedef bool result_type;
};// logical_or example
#include <iostream> // std::cout, std::boolalpha
#include <functional> // std::logical_or
#include <algorithm> // std::transformint main () {bool foo[] = {true,false,true,false};bool bar[] = {true,true,false,false};bool result[4];std::transform (foo, foo+4, bar, result, std::logical_or<bool>());std::cout << std::boolalpha << "Logical OR:\n";for (int i=0; i<4; i++)std::cout << foo[i] << " OR " << bar[i] << " = " << result[i] << "\n";return 0;
}
- not? ?logical_not<T>
template <class T> struct logical_not {bool operator() (const T& x) const {return !x;}typedef T argument_type;typedef bool result_type;
};// logical_not example
#include <iostream> // std::cout, std::boolalpha
#include <functional> // std::logical_not
#include <algorithm> // std::transformint main () {bool values[] = {true,false};bool result[2];std::transform (values, values+2, result, std::logical_not<bool>());std::cout << std::boolalpha << "Logical NOT:\n";for (int i=0; i<2; i++)std::cout << "NOT " << values[i] << " = " << result[i] << "\n";return 0;
}
證同、選擇、投射
- 這一章節的仿函數只是將參數原封不動的傳回
- 其中某些仿函數對傳回的參數有刻意的選擇 、或者刻意的忽略