C++之仿函数与配接器bind

东阳的学习笔记

所谓仿函数,是一个定义了 operator()的对象。

仿函数的三大妙处

  1. 仿函数比一般函数更灵巧,因为它可以拥有状态
  2. 每个仿函数都有其类别。因此你可以将仿函数作为 template 参数来传递,从而指定某种行为模式。此外还有一个好处:容器类别也会因为仿函数的不同而不同
  3. 仿函数的执行速度比函数指针更快

一个拥有内部状态的仿函数例子

如果要保存状态,则需以reference传递参数, 或者使用 for_each 的返回值(没错,for_each返回操作).

/*
 * genera2.cpp
 *
 *  Created on: 2021年1月14日
 *      Author: san
 */

#include <iostream>
#include <list>
#include <algorithm>
#include "print.hpp"
using namespace std;

class IntSequence {
private:
	int value;
public:
	// constructor
	IntSequence(int initalvalue)
		:value(initalvalue)
	{
	}

	// function call
	int operator() ()
	{
		return value++;
	}
};

int main()
{
	list<int> coll;
	IntSequence seq(1);

	/* insert values from 1 - 4
	 * - pass function object by reference
	 * so that it will continue with five
	 */
	generate_n<back_insert_iterator<list<int> >,
			int, IntSequence &>(back_inserter(coll),   // start
					4,								   // number of elements
					seq);                              // generates values

	PRINT_ELEMENTS(coll);

	// insert value from 42 - 45
	generate_n(back_inserter(coll),
			3,
			IntSequence(42));

	// print coll
	PRINT_ELEMENTS(coll, "append 42-45: ");

	// continue insert with sep
	generate_n(back_inserter(coll),
			5,
			seq);

	// print coll
	PRINT_ELEMENTS(coll, "add continue: ");
}

配接器

所谓的“函数配接器”是指可以把仿函数和另一个仿函数(或某个值,或某个一般函数)结合起来的仿函数。函数配接器也定义在头文件<functional>中。

占位符 std::placeholder

C++11的新特性:占位符std::placeholders,其定义如下:

namespace placeholders {
  extern /* unspecified */ _1;
  extern /* unspecified */ _2;
  extern /* unspecified */ _3;
  // ...
}

其中 _1 表示回调函数中的第一个参数,_2表示第二个参数…以此类推

C++11中,对C++98标准中函数适配器bind1st/bind2nd进行了泛化和增强,可以传递任何数量的参数

int Add(int num1, int num2)
{
    return (num1 + num2);
}

Add(1,2);
//等价于一个具有无参operator()的bind函数对象调用
std::bind(&Add,1,2)();

int Sub(int num1,int num2)
{
    return (num1 - num2);
}
std::bind(&Sub,std::placeholders::_1,std::placeholders::_2)(2,1);
//等价于
Sub(2,1);
std::bind(&Sub,std::placeholders::_2,std::placeholders::_1)(2,1);
//等价于
Sub(1,2);  

组合型仿函数(也称组合型函数配接器)

使用仿函数,将两个另外的组合,没啥特殊的,下面是一个嵌套的例子:

/*
 * compose11.hpp
 *
 *  Created on: 2021年1月9日
 *      Author: san
 */

#ifndef FO_COMPOSE11_HPP_
#define FO_COMPOSE11_HPP_

#include <functional>

/*
 * 一元组合函数配接器
 */

template <class OP1, class OP2>
class compose_f_gx_t
		: public std::unary_function<typename OP2::argument_type,  // Be careful, OP2 is the first
		  	  	  	  	  	  	  	 typename OP1::result_type>
{
private:
	OP1 op1;  // preocess: op1(op2(x));
	OP2 op2;
public:
	// constructor
	compose_f_gx_t(const OP1 &o1, const OP2 &o2)
		: op1(o1), op2(o2) {
	}

	// function call
	typename OP1::result_type
	operator() (const typename OP2::argument_type &x)
	{
		return op1(op2(x));
	}
};

/*
 * convenience functions for the compose_f_ gx adapter
 */
template <class OP1, class OP2>
inline compose_f_gx_t<OP1, OP2>
compose_f_gx (const OP1 &o1, const OP2 &o2) {
	return compose_f_gx<OP1, OP2>(o1, o2);
}

#endif /* FO_COMPOSE11_HPP_ */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东阳z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值