绑定器和函数对象operator()
1.C++ STL中的绑定器
bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值
2.C++11从Boost库中引入了bind绑定器和function函数对象机制
3.lambda表达式 底层依赖函数对象的机制实现的
我们先准备好环境
#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 < 20; ++i)
{
vec.push_back(rand() % 100 + 1);//随机出来的数字,并不是有序的
}
showContainer(vec);
sort(vec.begin(), vec.end());//默认小到大排序,传入的是起始和末尾的后继的迭代器
showContainer(vec);
//greater 二元函数对象
sort(vec.begin(), vec.end(), greater<int>());//大到小排序
showContainer(vec);
return 0;
}
C++ STL的绑定器
把70按顺序插入到vec容器当中,找第一个小于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();
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);
sort(vec.begin(), vec.end());//默认小到大排序
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;
}
C++ 11的绑定器(function使用示例)
void hello1()
{
cout << "hello world!" << endl;
}
void hello2(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()
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;
}
#include <iostream>
#include <vector>
#include <map>
#include <functional>//使用function函数对象类型
#include <algorithm>
#include <ctime>
#include <string>
using namespace std;
void doShowAllBooks() { cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
void doQueryBooks() { cout << "查询书籍" << endl; }
void doLoginOut() { cout << "注销" << endl; }
int main()
{
int choice = 0;
// C的函数指针
map<int, function<void()>> actionMap;
actionMap.insert({ 1, doShowAllBooks });//老版本:insert(make_pair(xx,xx));
actionMap.insert({ 2, doBorrow });
actionMap.insert({ 3, doBack });
actionMap.insert({ 4, doQueryBooks });
actionMap.insert({ 5, doLoginOut });
for (;;)
{
cout << "-----------------" << endl;
cout << "1.查看所有书籍信息" << endl;
cout << "2.借书" << endl;
cout << "3.还书" << endl;
cout << "4.查询书籍" << endl;
cout << "5.注销" << endl;
cout << "-----------------" << endl;
cout << "请选择:";
cin >> choice;
auto it = actionMap.find(choice);//map pair first second
if (it == actionMap.end())
{
cout << "输入数字无效,重新选择!" << endl;
}
else
{
it->second();
}
//不好,因为这块代码无法闭合 无法做到“开-闭原则”
/*switch (choice)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
default:
break;
}*/
}
return 0;
}
模板的完全特例化和部分特例化
模板的完全特例化和非完全(部分)特例化
模板的实参推演 => 基本概念很简单
有完全特例化,就选择对应的完全特例化,有部分特例化,就匹配部分特例化,没有的话,就原模板实例化
示例1
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;
}
第二个是特例化了。
示例2
template<typename T>
class Vector
{
public:
Vector() { cout << "call Vector template init" << endl; }
};
//下面这个是对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)
func2(sum);
func3(&Test::sum);//int (__thiscall Test::*)(int,int)
return 0;
}
function的实现原理
#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 {};
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;
};
///
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()
{
function<void(string)> func1(hello);
func1("hello world!");//func1.operator()("hello world!")
myfunction<int(int, int)> func2(sum);
cout << func2(10, 20) << endl;
return 0;
}
C++11 绑定器介绍
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!")();//返回的结果是绑定器,也就是函数对象
cout << bind(sum, 10, 20)() << endl;
cout << bind(&Test::sum, Test(), 20, 30)() << endl;
//参数占位符 绑定器出了语句,无法继续使用
//只是占位的作用,调用的时候就要传递参数了
//书写的时候使用多少个占位符,就是意味着用户调用的时候要传入几个参数
bind(hello, _1)("hello bind 2!");
cout << bind(sum, _1, _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;
}
有20个参数占位符