原文:function模板(functional头文件),算术、关系、逻辑运算模板
function模板
不同类型的对象可能共享同一种调用形式。例如下面的三种类型,都共享同一种调用形式:int(int,int);
int add(int i, int j) { return i + j; }
auto mod = [](int i, int j) {return i * j; };
struct divide
{
int operator()(int denominator,int divisor)
{
return denominator / divisor;
}
};
为了使用这些可调用对象,我们可以定义一个函数表用于存储指向这些可调用对象的“指针”。我们可以通过map来实现:
- 参数1用一个string来表示这个对象可以用来干嘛
- 参数2为函数指针
map<string, int(*)(int,int)> binops;
binops.insert({ "+",add });//正确
binops.insert({ "%",mod });//错误
- 然后第二个是错误,因为lambda是个表达式,每个lambda都有自己的类类型,该类型与存储在binops中的值的类型不匹配
一、function模板简介
- 我们可以用function的标准库类型解决上述问题
- 新版本标准库中的function类与旧版本中的unary_function和binary_function没有关联,后两个类已经被更通用的bind函数替代了
二、使用
- 当使用该模板时,必须提供额外的信息来表示能够表示的对象的调用形式
演示案例
- function模板接受两个int、返回一个int的可调用对象
function<int(int, int)> f1 = add;
function<int(int, int)> f2 = divide();
function<int(int, int)> f3 = [](int i, int j) {return i*j; };
cout << f1(4,2)<< endl; //6
cout << f2(4, 2) << endl;//2
cout << f3(4, 2) << endl;//8
重新定义map
- 我们通过使用function模板重新定义上面的map
map<string, function<int(int, int)>> binops;
binops = {
{"+",add},
{"-",std::minus<int>()},
{"/",divide()},
{"*",[](int i,int j) {return i*j; }},
{"%",mod}
};
binops["+"](10, 5); //调用add(10,5);
binops["-"](10, 5); //使用minus<int>对象的调用运算符
binops["/"](10, 5); //使用divide对象的调用运算符
binops["*"](10, 5); //调用lambda函数对象
binops["%"](10, 5); //调用lambda函数对象
三、重载的函数与function模板的关系
- 规则:不能直接将重载函数的名字存入到function类型的对象中,会产生二义性
- 解决方法:在模板中存储函数指针而非函数的名字
错误演示以及正确案例
- 错误案例
int add(int i, int j);
long add(long i, long j);
map<string, function<int(int, int)>> binops;
binops.insert({ "+",add });//错误,产生二义性
- 正确方法
int add(int i, int j);
long add(long i, long j);
int(*fp)(int, int) = add; //函数指针
map<string, function<int(int, int)>> binops;
binops.insert({ "+",fp });//正确
- 同样,我们也能使用lambda来消除二义性。lambda内部的函数传入了两个int,因此该调用只能匹配接受两个int的add函数版本,而这也正是执行lambda时真正调用的函数
算术、关系、逻辑运算模板(functional头文件)
一、functional头文件包含的对象
二、使用场景
- 标准库定义了一组表示算术运算符、关系运算符、逻辑运算符的类,每个类分别定义了一个执行命名操作的调用运算符
- 这些类都被定义成模板的形式,我们可以为其制定具体的应用类型
例如:
- plus类:定义了一个函数调用运算符用于对一对运算对象执行“+”操作
- modulus类:定义了一个调用运算符执行二元的“%”操作
- negate类:对数取反
- equal_to类执行“==”
等等......
三、演示案例
- plus与negate演示
plus<int> intAdd;
negate<int> intNegate;
int sum = intAdd(10, 20); //sum=10+20=30
sum = intNegate(intAdd(10, 20));//sum=-30(先得到30然后取反)
sum = intAdd(10, intNegate(10));//sum=10-10=0
- greater演示
- 默认情况下,sort会按照升序排列,使用了下面之后,sort就按照降序排列