1. 5种形式
可调用对象有5种形式,类型各不同:
形式 | 解释 |
---|---|
函数 | 返回值类型和实参类型 |
函数指针 | 返回值类型和实参类型 |
lambda表达式 | 类类型 |
bind创建的对象 | todo |
重载了函数调用运算符的类 | 类类型 |
2. 虽然可调用对象类型不同,但是调用形式可以一样
调用形式指明了调用返回的类型以及传递给调用的实参类型。不同的可调用对象可能具有相同的调用形式。
eg. 类型都为int(int, int)
// ordinary function
int add(int i, int j) {
return i + j; }
//lambda表达式,其产生一个未命名的函数对象类
auto mod = [](int i, int j) {
return i % j; };
// function-object class
struct divide
{
int operator()(int denominator, int divisor)
{
return denominator / divisor;
}
};
//调用代码
//使用map映射
map<string,function<int(int,int)> > binops;
binops.insert({
"+", add});
//error,不能将mode或divide insert到binope中,因为他们类型不是函数指针
binops.insert({
"%", mod});
有个问题:不能统一调用
3. 如何统一调用?
标准库function类型:标准库function类型是一个模板,定义在头文件functional中,用来表示对象的调用形式。
使用时需要创建一个具体的function类型。(必须提供其所表示的对象的调用形式)
操作 | 解释 |
---|---|
function f; | f是一个用来存储可调用对象的空function,这些可调用对象的调用形式应该与类型T相同。 |
function f(nullptr); | 显式地构造一个空function |
function f(obj) | 在f中存储可调用对象obj的副本 |
f | 将f作为条件:当f含有一个可调用对象时为真;否则为假。 |
定义为function的成员的类型f(args) | 调用f中的对象,参数是args |
result_type | 该function类型的可调用对象返回的类型 |
argument_type | 当T有一个或两个实参时定义的类型。 |
first_argument_type | 第一个实参的类型 |
second_argument_type | 第二个实参的类型 |
eg. function<int(int, int)>
function<int(int,int)> f1=add; //函数指针
function<int(int,int)> f2=divide(); //函数对象类的指针
function<int(int,int)> f3=[](int i,int l){
return i*j;}; //lambda
cout << f1(4,2) << endl; // prints 6
cout << f2(4,2) << endl; // prints 2
cout << f3(4,2) << endl; // prints 8
eg2.
//使用map映射
map<string,function<int(int,int)> > binops={
{
"+",add}, //函数指针
{
"-",std::minus<int>()}, //标准库函数对象
{
"/",divide()}, // 用户定义的函数对象
{
"*",[](int i,int j){
return i*j;}}, //未命名的lambda
{
"%",mod} //已命名的lambda对象
};
//这个时候insert是可以的
binops.insert( {
"+", add} ); //函数指针
binops.insert( {
"/",divide()} ); //函数对象
binops.insert( {
"%", mod} ); //lambda表达式
binops.insert({
"+"},[](int a,in b){
return add(a,b);});//lambda表达式
binops.insert({
"add" , [](int a, int b) {
return add(a, b); } });//lambda表达式
cout << binops["+"](10, 5)<<endl;//调用add(10, 5)
cout << binops["-"](10, 5) << endl;
cout << binops["/"](10, 5) << endl; //使用divide对象调用括号运算符
cout << binops["*"](10, 5) << endl;
cout << binops["%"](10, 5) << endl;//调用lambda函数对象
cout << binops["add"](10, 5) << endl;//调用lambda函数对象
3.1 不能直接将重载函数的名字存入 function 类型的对象中,这样做会产生二义性错误。
int add(int i,int j){
return i + j;}
Sales_data add(const Sales_data&,const Sales_data&);
map<string,funciton<int(int,int)>> binops;
binops.insert({
"+",add}); //错误,不能区分是哪个add
3.2 解决方法
存储函数指针而非函数名字:
int (*fp) (int,int) = add;
binops.insert("add",fp); //正确,fp指向正确的add版本
- C++11新标准库中的function类与旧版本中的unary_function和binary_function没有关系,后两个类已经被bind函数代替。
【引用】