原文来自:http://www.hankcs.com/program/cpp/c11-std-function-usage.html
在看Cocos2d-x的范例代码时,随处可见“很奇怪”的语法:
1
2
3
4
5
|
static
std::function<Layer*()> createFunctions[] =
{
CL(CameraTest1),
//...
};
|
其中CL是一个宏,对应如下lambda表达式:
1
|
#define CL(__className__) [](){ return __className__::create();}
|
还算好懂,感觉是个工厂模式,同时用宏模拟了接口。
但是这个std::function<Layer*()>却让我少见多怪了,翻开第五版《C++ Primer》,才知道原来是C++11的新特性——可调用对象模板类。一句话说明问题,std::function<Layer*()>代表一个可调用对象,接收0个参数,返回Layer*。
至于function的深入理解,还是用代码说明吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#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标准的不同实现吧。
自从学了C++11和Java8,再也不怕同事看懂我的代码啦~