std::bind和std::function详解
2016-10-20 09:42
309 查看
std::function
在看Cocos2d-x的范例代码时,随处可见“很奇怪”的语法:static std::function<Layer*()> createFunctions[] =
{
CL(CameraTest1),
//...
};
其中CL是一个宏,对应如下lambda表达式:#define CL(__className__) [](){ return __className__::create();}
还算好懂,感觉是个工厂模式,同时用宏模拟了接口。
但是这个std::function<Layer*()>却让我少见多怪了,翻开第五版《C++ Primer》,才知道原来是C++11的新特性——可调用对象模板类。一句话说明问题,std::function<Layer*()>代表一个可调用对象,接收0个参数,返回Layer*。
至于function的深入理解,还是用代码说明吧。#include <iostream>
#include <map>
#include <functional>
using namespace std;
// 普通函数
int add(int i, int j) { return i + j; }
// lambda表达式
auto mod = [](int i, int j){return i % j; };
// 函数对象类
struct divide
{
int operator() (int denominator, int divisor)
{
return denominator / divisor;
}
};
///////////////////////////SubMain//////////////////////////////////
int main(int argc, char *argv[])
{
// 受限的map
map<char, int(*)(int, int)> binops_limit;
binops_limit.insert({ '+', add });
binops_limit.insert({ '%', mod });
// 错误 1 error C2664: “void std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::insert(std::initializer_list<std::pair<const _Kty,_Ty>>)”: 无法将参数 1 从“initializer-list”转换为“std::pair<const _Kty,_Ty> &&”
// binops_limit.insert({ '%', divide() });
// 更灵活的map
map<char, function<int(int, int)>> binops =
{
{ '+', add },
{ '-', minus<int>() },
{ '*', [](int i, int j){return i - j; } },
{ '/', divide() },
{ '%', mod },
};
cout << binops['+'](10, 5) << endl;
cout << binops['-'](10, 5) << endl;
cout << binops['*'](10, 5) << endl;
cout << binops['/'](10, 5) << endl;
cout << binops['%'](10, 5) << endl;
system("pause");
return 0;
}
///////////////////////////End Sub//////////////////////////////////
如上所示,function可以将普通函数,lambda表达式和函数对象类统一起来。它们并不是相同的类型,然而通过function模板类,可以转化为相同类型的对象(function对象),从而放入一个map里。
另外我实际测试的结果来看,在VS2013编译器下,上述代码可以通过,而第五版《C++ Primer》第512页第一行所言“错误:mod不是一个函数指针”并没有发生错误,有可能是对C++11标准的不同实现吧。
std::bind
http://blog.chinaunix.net/uid-20726254-id-3483489.html虽然也在泛型那一章,但这个挺好玩的,单拿出来总结下,越来越有python的感觉.
std::bind通俗说就是一个 callabe adapter,因为有些场合需要的callable的参数个数不一样,可能实现差不多,完全重写又价值不大,以前的版本有bind1st和bind2nd,在c++11中这哥俩已经deprecated了,没准哪天就彻底game over了。
bind的语法格式:auto newCallable = bind(callable, arg_list); 看个简单例子
点击(此处)折叠或打开
#include<functional>
using namespace std::placeholders;
void f5(int i,int j)
{
if(i<j> cout<<i<<endl;
else cout<<j<<endl;
}
auto f_bind=bind(f5,_1,10);
int main(){
f_bind(6);
f_bind(10);
cout<<"end in main \n"<<endl;
return 0
}
首先bind在functional头文件中,记得引入。f5函数比较2个参数大小,输出小的。可是某些场景下,我们想要带一个参数的比较函数,内部直接和10进行比较,这时就可以把f5用bind包裹一下。
新函数是f_bind,右侧bind的参数里带下划线的数字称为placeholder,表示新函数的第几个参数,当然最大的数值就是f_bind的参数个数。词条语句的意思是新函数f_bind包裹了f5,其第一个也是唯一的参数作为f5的第一个参数,同时将整数10作为f5的第二个参数传入。
placeholder在std内部定义的placeholders空间内,如果不用using声明下就要使用全称。其数值的编号要按顺序,但在bind参数列表可以不按书序出现:
点击(此处)折叠或打开
auto g = bind(f, a, b, _2, c, _1);
g(X, Y) ;
f(a, b, Y, c, X);
书中这个例子对照一看就应该明白了。g(X,Y)等于调用了f(a,b,Y,c,X);
bind和lambda表达式一样,默认都是传值的,如果想要用引用,需要ref或cref函数,后者是常引用,也都位于functional头文件。
auto g = bind(f, ref(a), cref(b).....)
std::function std::bind 区别 http://blog.csdn.net/qq575787460/article/details/8531397
此篇解释的非常好 http://www.cnblogs.com/slysky/p/3822640.html
相关文章推荐
- std::bind与std::function详解
- C++11 中std::function和std::bind用法详解
- std::function和std::bind详解
- C++11中lambda、std::function和std:bind详解
- std::bind与std::function详解
- C++ 11 std::function std::bind使用
- c++11 std::bind与std::function
- std::bind和std::function
- C++11新特性之std::function & std::bind
- C++11 std::function、std::bind
- lambda, std::function, std::bind
- c++中的std::bind与std::function
- c++11特性与cocos2d-x 3.0之std::bind与std::function
- 函数指针&绑定: boost::functoin/std::function/bind
- C++11 中std::function和std::bind的用法
- std::function 和 std::bind
- VC11, std functional bind/function, big performance hit under x64
- std::function与std::bind 函数指针
- C++14:std::bind和std::function
- 函数指针&绑定: boost::functoin/std::function/bind