放牧代码和思想
专注自然语言处理、机器学习算法
    This thing called love. Know I would've. Thrown it all away. Wouldn't hesitate.

C++11 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标准的不同实现吧。

自从学了C++11和Java8,再也不怕同事看懂我的代码啦~

知识共享许可协议 知识共享署名-非商业性使用-相同方式共享码农场 » C++11 std::function用法

评论 7

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #6

    最后一句吊炸天了

    longhaiqwe6年前 (2018-09-17)回复
  2. #5

    map里面的乘法算法{ ‘*’, [](int i, int j){return i – j; } },应该是{ ‘*’, [](int i, int j){return i * j; } },不过写的很好!

    rex_yan7年前 (2018-01-16)回复
  3. #4

    为何我在2012上编译通不过

    蔡聪敏9年前 (2016-03-22)回复
  4. #3

    赞啊,再也不怕同时看懂我代码了 哈哈哈

    九日行空9年前 (2015-07-24)回复
  5. #2

    " 第五版《C++ Primer》第512页第一行所言“错误:mod不是一个函数指针”并没有发生错误"
    书上说的是,当你将map容器定义为 map<string, int(*)(int, int)> binops;时,会无法存入mod,因为mod是一个lambda表达式。
    而你定义的是 map<char, function<int(int, int)> > binops; 自然编译器不会报错。
    [呵呵]

    MacroFun10年前 (2015-05-23)回复
  6. #1

    赞~

    o__nly10年前 (2015-05-03)回复

我的作品

HanLP自然语言处理包《自然语言处理入门》