bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值
将数组从大到小排序后,按顺序插入70
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <ctime> using namespace std; template<typename Container> void showContainer(Container& con) { typename Container::iterator it = con.begin(); //编译器是从上到下编译的,这个还没有实例化,它不知道这个名字作用域后面的iterator是类型还是变量 //typename告知编译器后面类型的作用域后面是类型 for (; it != con.end(); ++it) { cout << *it << " "; } cout << endl; } int main() { vector<int> vec; srand(time(nullptr)); for (int i = 0; i < 10; ++i) { vec.push_back(rand() % 100 + 1);//随机出来的数字,并不是有序的 } showContainer(vec); //greater 二元函数对象 sort(vec.begin(), vec.end(), greater<int>());//大到小排序 showContainer(vec); //把70按顺序插入到vec容器当中,找第一个小于70的数字 auto it1 = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70)); //auto it1 = find_if(vec.begin(), vec.end(),bind2nd(less<int>(), 70)); if (it1 != vec.end()) { vec.insert(it1, 70); } showContainer(vec); return 0; }
// FUNCTION TEMPLATE find_if template<class _InIt, class _Pr> _NODISCARD inline _InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) { // find first satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); for (; _UFirst != _ULast; ++_UFirst) { if (_Pred(*_UFirst)) { break; } } _Seek_wrapped(_First, _UFirst); return (_First); }
其中第三个参数_Pred是一个一元函数对象
// FUNCTION TEMPLATE bind1st template<class _Fn, class _Ty> _NODISCARD inline binder1st<_Fn> bind1st(const _Fn& _Func, const _Ty& _Left) { // return a binder1st functor adapter typename _Fn::first_argument_type _Val(_Left); return (binder1st<_Fn>(_Func, _Val)); }
它是一个函数模板,返回一元函数对象binder1st
// CLASS TEMPLATE binder1st template<class _Fn> class binder1st : public unary_function<typename _Fn::second_argument_type, typename _Fn::result_type> { // functor adapter _Func(stored, right) public: typedef unary_function<typename _Fn::second_argument_type, typename _Fn::result_type> _Base; typedef typename _Base::argument_type argument_type; typedef typename _Base::result_type result_type; binder1st(const _Fn& _Func, const typename _Fn::first_argument_type& _Left) : op(_Func), value(_Left) { // construct from functor and left operand } result_type operator()(const argument_type& _Right) const { // apply functor to operands return (op(value, _Right)); } result_type operator()(argument_type& _Right) const { // apply functor to operands return (op(value, _Right)); } protected: _Fn op; // the functor to apply typename _Fn::first_argument_type value; // the left operand };
一元函数对象默认构造函数接受两个参数, op和 value。赋值运算符接收一个参数,并使用传入的op和vaule 进行运算:op(value, _Right)
简单的实现如下:
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <ctime> using namespace std; template<typename Container> void showContainer(Container& con) { typename Container::iterator it = con.begin(); for (; it != con.end(); ++it) { cout << *it << " "; } cout << endl; } template<typename Iterator, typename Compare> Iterator my_find_if(Iterator first, Iterator last, Compare comp) //遍历这2个迭代器之间的元素,如果满足函数对象的运算,就返回当前迭代器,如果都不满足,返回end() { for (; first != last; ++first) { if (comp(*first))//comp.operator()(*first)一元函数对象,因为要从容器拿1个元素和它指定的元素比较 //my_find_if需要1元函数对象,而在库里面都是二元的 { return first; } } return last; } template<typename Compare, typename T> class _mybind1st//绑定器是函数对象的一个应用 { public: _mybind1st(Compare comp, T val) :_comp(comp), _val(val) {} bool operator()(const T& second) { return _comp(_val, second);//greater } private: Compare _comp; T _val; }; //mybind1st(greater<int>(), 70) template<typename Compare, typename T> _mybind1st<Compare, T> mybind1st(Compare comp, const T& val) { //直接使用函数模板,好处是,可以进行类型的推演 return _mybind1st<Compare, T>(comp, val); } int main() { vector<int> vec; srand(time(nullptr)); for (int i = 0; i < 20; ++i) { vec.push_back(rand() % 100 + 1); } showContainer(vec); //greater 二元函数对象 sort(vec.begin(), vec.end(), greater<int>());//大到小排序 showContainer(vec); /* 把70按顺序插入到vec容器当中 找第一个小于70的数字 operator()(const T &val) greater a > b less a < b 绑定器 + 二元函数对象 =》 一元函数对象 bind1st: + greater bool operator()(70, const _Ty& _Right) bind2nd: + less bool operator()(const _Ty& _Left, 70) */ auto it1 = my_find_if(vec.begin(), vec.end(), mybind1st(greater<int>(), 70)); //auto it1 = my_find_if(vec.begin(), vec.end(),bind2nd(less<int>(), 70)); if (it1 != vec.end()) { vec.insert(it1, 70); } showContainer(vec); return 0; }
解决绑定器,函数对象,lambda表达式只能使用在一条语句中的问题;
定义:传递一个 _Fty function type 希望传递一个函数类型
// CLASS TEMPLATE function template<class _Fty> class function : public _Get_function_impl<_Fty>::type { // wrapper for callable objects private: typedef typename _Get_function_impl<_Fty>::type _Mybase; public: function() noexcept { // construct empty function wrapper }
简单使用:
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <ctime> #include <string> using namespace std; void hello1() { cout << "hello world!" << endl; } void hello2(const string &str)//void (*pfunc)(string) { cout << str << endl; } int sum(int a, int b) { return a + b; } class Test { public://必须依赖一个对象void (Test::*pfunc)(string) void hello(string str) { cout << str << endl; } }; int main() { /* 1.用函数类型实例化function 2.通过function调用operator()函数的时候,需要根据函数类型传入相应的参数 */ //从function的类模板定义处,看到希望用一个函数类型实例化function function<void()> func1 = hello1; func1();//func1.operator()() => hello1() function<void(string)> func2 = hello2; func2("hello hello2!");//func2.operator()(string str) => hello2(str) function<int(int, int)> func3 = sum; cout << func3(20, 30) << endl; //operator() lambda 表达式 function<int(int, int)> func4 = [](int a, int b)->int {return a + b; }; cout << func4(100, 200) << endl; //类成员函数 function<void(Test*, string)> func5 = &Test::hello; func5(&Test(), "call Test::hello!");//临时对象调用 return 0; }
对于下面的compare,对于char类型的比较不能满足实际的需要,因此对compare特例化一个版本compare<const char *>
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <ctime> #include <string> using namespace std; template<typename T> bool compare(T a, T b) { cout << "template compare" << endl; return a > b; } template<> bool compare<const char*>(const char*a, const char*b)//特例化 { cout << "compare<const char*>" << endl; return strcmp(a, b) > 0; } int main() { compare(10, 20);// compare("aaa", "bbb");//T const char* return 0; }
匹配原则:有完全特例化则先匹配完全特例化,其次部分特例化,最后函数模板
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <ctime> #include <string> using namespace std; //类模板 template<typename T> class Vector { public: Vector() { cout << "call Vector template init" << endl; } }; //下面这个是对char*类型提供的完全特例化版本(<>中T已知:即下面的char *) #1 template<>//特例化的语法 class Vector<char*> { public: Vector() { cout << "call Vector<char*> init" << endl; } }; //下面这个是对指针类型提供的部分特例化版本 #2 //仅知道是一个指针,类型需要提供 template<typename Ty> class Vector<Ty*> { public: Vector() { cout << "call Vector<Ty*> init" << endl; } }; //指针函数指针(有返回值,有两个形参变量)提供的部分特例化 template<typename R, typename A1, typename A2> class Vector<R(*)(A1, A2)> { public: Vector() { cout << "call Vector<R(*)(A1, A2)> init" << endl; } }; //针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化 template<typename R, typename A1, typename A2> class Vector<R(A1, A2)> { public: Vector() { cout << "call Vector<R(A1, A2)> init" << endl; } }; int sum(int a, int b) { return a + b; } int main() { Vector<int> vec1; Vector<char*> vec2; Vector<int*> vec3; Vector<int(*)(int, int)> vec4; Vector<int(int, int)> vec5;//function //注意区分一下函数类型和函数指针类型 typedef int(*PFUNC1)(int, int); PFUNC1 pfunc1 = sum; cout << pfunc1(10, 20) << endl; typedef int PFUNC2(int, int); PFUNC2 *pfunc2 = sum; cout << (*pfunc2)(10, 20) << endl; return 0; }
实参推演:
#include <iostream> #include <typeinfo> using namespace std; int sum(int a, int b) { return a + b; } //T包含了所有的大的类型 返回值,所有形参的类型都取出来 template<typename T> void func(T a) { cout << typeid(T).name() << endl; } //细化返回值类型和参数类型 template<typename R, typename A1, typename A2> void func2(R(*a)(A1, A2)) { cout << typeid(R).name() << endl; cout << typeid(A1).name() << endl; cout << typeid(A2).name() << endl; } class Test { public: int sum(int a, int b) { return a + b; } }; //实参推演每一个类型 template<typename R, typename T, typename A1, typename A2> void func3(R(T::* a)(A1, A2)) { cout << typeid(R).name() << endl; cout << typeid(T).name() << endl; cout << typeid(A1).name() << endl; cout << typeid(A2).name() << endl; } int main() { func(10); func("aaa"); func(sum);//T int (*)(int,int) int (int,int) func(&Test::sum);//int (__thiscall Test::*)(int,int) // cout << "---------------------func2\n"; func2(sum); cout << "---------------------func3\n"; func3(&Test::sum);//int (__thiscall Test::*)(int,int) return 0; }
#include <iostream> #include <typeinfo> #include <string> #include <functional> using namespace std; /* function函数对象类型的实现原理 */ void hello(string str) { cout << str << endl; } int sum(int a, int b) { return a + b; } //定义个函数模板 template<typename Fty> class myfunction {}; //部分偏特化版本 <R(A1) template<typename R, typename A1> class myfunction<R(A1)> { public: using PFUNC = R(*)(A1); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A1 arg) { return _pfunc(arg);//hello(arg) } private: PFUNC _pfunc; }; /* //部分偏特化版本 R(*)(A1, A2); template<typename R, typename A1, typename A2> class myfunction<R(A1, A2)> { public: using PFUNC = R(*)(A1, A2); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A1 arg1, A2 arg2) { return _pfunc(arg1, arg2);//hello(arg) } private: PFUNC _pfunc; }; */ //通用版本 template<typename R, typename... A>//一组可变参数个数:表示一组类型 class myfunction<R(A...)> { public: using PFUNC = R(*)(A...); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A... arg)//一组形参变量 { return _pfunc(arg...);//hello(arg) 表示一组形参变量 } private: PFUNC _pfunc; }; int main() { myfunction<void(string)> func1(hello); func1("hello world!");//func1.operator()("hello world!") myfunction<int(int, int)> func2(sum); cout << func2(10, 20) << endl; return 0; }
fuction 底层是一个可变参的偏特化函数对象
C++11 bind绑定器,是一个函数模板 ,可以自动推演模板类型参数=> 返回的结果还是一个函数对象
bind占位符最多有20个参数
#include <iostream> #include <typeinfo> #include <string> #include <memory> #include <vector> #include <functional> #include <thread> using namespace std; using namespace placeholders; /* C++11 bind绑定器 => 返回的结果还是一个函数对象 */ void hello(string str) { cout << str << endl; } int sum(int a, int b) { return a + b; } class Test { public: int sum(int a, int b) { return a + b; } }; int main() { //bind是函数模板 可以自动推演模板类型参数 bind(hello, "hello bind!")();//返回的结果是绑定器,也就是函数对象 最后一个()表示调用函数对象的operator() cout << bind(sum, 10, 20)() << endl; cout << bind(&Test::sum, Test(), 20, 30)() << endl; //参数占位符 绑定器出了语句,无法继续使用 //只是占位的作用,调用的时候就要传递参数了 //书写的时候使用多少个占位符,就是意味着用户调用的时候要传入几个参数 bind(hello, placeholders::_1)("hello bind 2!"); cout << bind(sum, placeholders::_1, placeholders::_2)(200, 300) << endl; //此处把bind返回的绑定器binder就复用起来了 function<void(string)> func1 = bind(hello, _1); func1("hello china!"); func1("hello shan xi!"); func1("hello si chuan!"); return 0; }
placeholders 占位符:最多支持20个