仿函數(functor),就是使一個類的使用看上去像一個函數。其實現就是類中實現一個operator()
,這個類就有了相似函數的行爲,就是一個仿函數類了。ios
在STL中,將仿函數主要分爲了三大類:算術類(Arithmetic)、邏輯運算類(Logical)和相對關係類(Relational)。less
算術類(Arithmetic)舉例ide
template <class T> struct plus : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x + y; } }; template <class T> struct minus : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x - y; } }; ...
邏輯運算類(Logical)舉例函數
template <class T> struct logical_and : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x && y; } }; ...
相對關係類(Relational)網站
template <class T> struct equal_to : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x == y; } }; template <class T> struct less : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x < y; } }; ...
經過上面的代碼能夠發現,functors都繼承了一個基類。STL規定每一個 Adaptable Function 都應該挑選合適的父類繼承,由於 Adaptable Function 將會提問一些問題。this
template <class Arg, class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; }; template <class Arg1, class Arg2, class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; };
好比上面的less
經過繼承binary_function
擁有了3個typedef
,這些typedef
可能會在一些適配器中被詢問到,詳見後面適配器中的源碼。spa
Adapters 至關於一種修飾的做用,在容器、迭代器和仿函數的基礎上,對其進行一種改造。將改造完成後的容器、迭代器或仿函數交給用戶使用,但其核心仍是經過內部的容器、迭代器和仿函數進行工做。因此就存在: Container Adapters, Iterator Adapters 和 Functor Adapters三類。指針
stackcode
template <class T, class Sequence=deque<T>> class stack{ ... public: typedef typename Sequence::value_type value_type; typedef typename Sequence::size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; proctected: Sequence c;// 底層容器 public: bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference top() { return c.back(); } const_reference top const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void pop { c.pop_back(); } };
queue對象
template <class T, class Sequence=deque<T>> class queue{ ... public: typedef typename Sequence::value_type value_type; typedef typename Sequence::size_type size_type; typedef typename Sequence::reference reference; typedef typename Sequence::const_reference const_reference; proctected: Sequence c;// 底層容器 public: bool empty() const { return c.empty(); } size_type size() const { return c.size(); } reference front() { return c.front(); } const_reference front() const { return c.front(); } reference back() { return c.back(); } const_reference back() const { return c.bakc(); } void push(const value_tyoe& x) { c.push_back(x); } void pop { c.pop_back(); } };
對於這樣一行語句:
cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40));
首先須要注意的是less<int>()
這並非函數的調用,而是生成一個less<int>
的對象!
count_if
template <class InputIterator, class Predicate> typename iterator_traits<InputIterator>::difference_type count_if(InputIterator first, InputIterator last, Predicate pred){ typename iterator_traits<InputIterator>::difference_type n = 0; for(; first != last; ++first) if(pred(*first)) ++n; return n; }
bind2nd
template <class Operation, class T> inline binder2nd<Operation> bind2nd(const Operation& op,const T& x) { typedef typename Operator::second_argument_type arg2_type; return binder2nd<Operation>(op, arg2_type(x));//返回一個binder2nd<Operation>對象! }
binder2nd
template <class Operation> class binder2nd : public unary_function<typename Operation::first_argument_type, typename Operation::result_type> { protected: Operation op; typename Operation::second_argument_type value; public: binder2nd(const Operation& x,const typename Operation::second_argument_type& y): op(x), value(y){} typename Operation::result_type operator()(const typename Operation::first_argument_type& x) const { return op(x,value);//這裏纔是函數的調用 } };
在這些代碼中能夠看到適配器在詢問仿函數一些問題,這些問題就是仿函數繼承的基類中的typedef
。全部能回答出這些問題的仿函數都稱爲 Adaptable Function。
not1
template <class Predicate> inline unary_negate<Predicate> not1(consat Predicate& pred) { return unary_negate<Predicate>(pred); } template <class Predicate> class unary_negate : public unart_function<typename Predicate::argument_type, bool> { protected: Predicate pred; public: eplicit unary_negate(const Predicate& x) : pred(x) {} bool operator()(const typename Predicate::argument_type& x) const { return !pred(x); } };
bind 使用例子(摘自cplusplus網站)
#include <iostream> // std::cout #include <functional> // std::bind // a function: (also works with function object: std::divides<double> my_divide;) double my_divide (double x, double y) {return x/y;} struct MyPair { double a,b; double multiply() {return a*b;} }; int main () { using namespace std::placeholders; // adds visibility of _1, _2, _3,... // binding functions: auto fn_five = std::bind (my_divide,10,2); // returns 10/2 std::cout << fn_five() << '\n'; // 5 auto fn_half = std::bind (my_divide,_1,2); // returns x/2 std::cout << fn_half(10) << '\n'; // 5 auto fn_invert = std::bind (my_divide,_2,_1); // returns y/x std::cout << fn_invert(10,2) << '\n'; // 0.2 auto fn_rounding = std::bind<int> (my_divide,_1,_2); // returns int(x/y) std::cout << fn_rounding(10,3) << '\n'; // 3 MyPair ten_two {10,2}; // binding members: member function 其實有個 argument: this auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply() std::cout << bound_member_fn(ten_two) << '\n'; // 20 auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a std::cout << bound_member_data() << '\n'; // 10 return 0; }
std::bind 能夠綁定:
因此能夠如今能夠用bind
替換bind2nd
,改寫以下:
vector<int> v {15,37,94,50,73,58,28,98}; int n = count_if(v.cbegin(), v.cend(), not1(bind2nd(less<int>, 50))); cout << "n=" << n << endl;//5 vector<int> v {15,37,94,50,73,58,28,98}; int n = count_if(v.cbegin(), v.cend(), not1(bind(less<int>, _1, 50))); cout << "n=" << n << endl;//5
reverse_iterator:用來實現去反向指針rbegin(), rend()的實現。
reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { returun reverse_iterator(begin()); } template <class Iterator> class reverse_iterator { protected: Iterator current;//對應的正向迭代器 public: //逆向迭代器的5中 associated types 都和對應的正向迭代器相同 typedef typename iterator_traits<Iterator>::iterator_category iterator_category; typedef typename iterator_traits<Iterator>::value_type value_type; ... typedef Iterator iterator_type; // 表示正向迭代器 typedef reverse_iterator<Iterator> self;// 表示反向迭代器 public: explicit reverse_iterator(iterator_type x) : current(x) {} reverse_iterator(const self& x) : current(x.current) {} iterator_type base() const { return current; } reference operator*() const { //關鍵所在! 對於逆向迭代器的取值,就是將正向的迭代器退一位取值。 Iterator tmp = current; return *--tmp; } pointer operator->() const { return &(operator*()); } //前進便後退,後退便前進 self& operator++() { --current; return *this; } self& operator--() { ++current; return *this; } slef operator+(difference_type n) const { return self(current - n); } slef operator-(difference_type n) const { return self(current + n); } };
inserter: 將iteartor中的複製操做改成插入操做,而且將iteartor右移一個位子。可讓用戶執行表面上assign而實際上insert的行爲。
template <class Container> class insert_iterator { protected: Container* container; typename Container::iterator iter; pbulic: typedef output_iterator_tag iterator_category; insert_iterator(Container& x, typename Container::iterator i) : container(&x), iter(i) {} //對賦值操做符重載,以實現插入 insert_iterator<Contain>& operator=(const typename Container::value_type& value) { iter = container->insert(iter, value); ++iter; return *thisl } }; //輔助函數,幫助用戶使用insert_iterator template <class Container, class Iterator> inline insert_iterator<Container> inserter(Container& x, Iterator i) { typedef typename Container::iterator iter; return insert_iterator<Container>(x, iter(i)); }
ostream_iterator
先來看一個例子
#include <iostream> //std::cout #include <iterator> //std::ostream_iterator #include <vector> //std::vector #include <algorithm> //std::copy int main() { std::vector<int> myvector; for (int i = 1; i < 10; ++i) myvector.push_back(i * 10); std::ostream_iterator<int> out_it(std::cout, ","); std::copy(myvector.begin(), muvector.end(), out_it); return 0; }
輸出結果:
10,20,30,40,50,60,70,80,90,
首先來看看copy
這個函數作了什麼
template<class InputIterator first, InputIterator last,OutputIterator result> copy(InputIterator first,InputIterator last, OutputIterator result) { while(first != last) { *result = *first; ++result; ++first; } }
再對比着ostream_iterator
的源碼,就能分析出輸出的緣由:
template<class T,class chatT=char,class traits=char_traits<charT>> class ostream_iterator:public iterator<output_iterator_tag,void,void,void,void> { basic_ostream<charT,traits>* out_stream; const charT* delim; public: typedef charT char_type; typedef traits traits_type; typedef basic_ostream<charT,traits> ostream_type; ostream_iterator(ostream_type& s):out_stream(&s),delim(0){} ostream_iterator(onstream_type&s, const charT* delimiter):out_stream(&s),delim(delimiter){} ostream_iterator(const ostream_iterator<T,charT,traits>& x):ostream_iterator(x.out_stream),delim(x.delim){} ~ostream_iterator(){} ostream_iterator<T,chatT,traits>& operator=(const T& value){//關鍵點!! *out_stream << value; if(delim!=0) *out_stream << delim; return *this; } ostream_iterator<T,charT,traits>& operator*(){return *this;} ostream_iterator<T,charT,traits>& operator++(){return *this;} ostream_iterator<T,charT,traits>& operator++(int){return *this;} };
關鍵就在於重載了=
號運算符。
istream_iterator
仍是先看一個例子
#include <iostream> #include <iterator> int main() { double value1, value2; std::cout << "Please, insert two values:"; std::istream_iterator<double> eos; std::istream_iterator<double> iit(std::cin);//當建立對象時,就已經在要求輸入了 if (iit != eos) value1 = *iit; ++iit; if (iit != eos) value2 = *iit; std::cout << value1 << "*" << value2 << "=" << (value1*value2) << "\n"; return 0; }
這個例子就是一個簡單的乘法,其中std::istream_iterator<double> iit(std::cin);
至關於cin >> value;
。具體的原理仍是看源碼吧。
template <class T, class charT = char, class traits = char_traits<charT>>, class Distance = ptrdiff_t > class istream_iterator : public iterator<input_iterator_tag, T, Distance, const T*, const T&> { basic_istream<charT, traits>* instream; T value; public: typedef charT char_type; typedef traits traits_type; typedef basic_istream<charT, traits> istream_type; istream_iterator() :instream(0) {} istream_iterator(istream_type& s) :in_stream(&s) { ++*this; } istream_iterator(const istream_iterator) < T, charT, traits, Distance > & x):in_stream(x.in_stream), value(x.value){} ~istream_itetator() {} const T& operator*() const { return value; } const T* operator->() const { return value; } istream_iterator<T, charT, traits, Distance>& operator++() { if (in_stream && !(*in_stream >> value)) in_stream = 0; return *this; } istream_iterator<T,charT,traits,Distance>operator++(int) { istream_iterator<T, charT, traits, Distance> tmp = *this; ++*this; return tmp; } };
對照源碼能夠發現,std::istream_iterator<double> iit(std::cin);
這裏調用了istream_iterator的++符號,此時就已經開始輸入了。