STL C++ std::bind操作例子,仿函数操作配合算法库操作

1、stl::bind 和std::mem_fun_ref系列的配合使用出现了问题,多参形式不知道如何组织。适配器的操作真心难受!!!只能迷迷糊糊地用着。要使用非质变算法时需要作用于容器时只能考虑lambda或者transfer操作。待续

// functor-adapter_p431.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <algorithm>//元素操作算法
#include <functional> //函数配接器,bind、compose、negate
#include <iostream>
#include <iterator>
#include <vector>
#include <memory>

using std::cout;
using std::cin;
using std::endl;

bool print(int i)
{
	std::cout<< i << " ";
	return true;
}

class Int
{
public:
	explicit Int(int i):m_i(i){};
	~Int(void){};

	void print1(void) const
	{
		cout<<"["<<m_i<<"]";
	}
	void print2(Int &i)const
	{
		cout<<"["<<i.m_i<<"]";
	}
	static void print3(Int &i)
	{
		cout<<"["<<i.m_i<<"]";
	}

int m_i;

private:

};

Int operator + (const Int &lhi,const Int &rhi)
	{
		Int temp(lhi.m_i);
		temp.m_i+=rhi.m_i;
		return temp;
	}

typedef bool (*FunPtr)(int);
typedef std::function<void ()> FunObejct;  

class A
{
public:
    virtual void f()
    {
        std::cout<<"A::f()"<<endl;
    }  

    void init()
    {
        //std::bind可以表现出多态行为
        FunObejct f=std::bind(&A::f,this);
        f();
    }
	bool print(int i)
	{
		std::cout<< i << ":";
		return true;
	}

	inline bool operator() (int i)
	{
		std::cout<< i << "/";
		return true;
	}

};  

class B:public A
{
public:
    virtual void f()
    {
        cout<<"B::f()"<<endl;
    }
};  

void inc(int &a)
{
	++a;
}

int _tmain(int argc, _TCHAR* argv[])
{
	std::ostream_iterator<int> out_it(cout,",");//输出迭代器绑定到命令窗输出行中,每次输出填充一个,和print区别开来

	int ia[6] = {2,21,12,7,19,23};

	std::shared_ptr<A>pa(new B()); //父类指针指向子类对象
    pa->init(); //多态、函数绑定实现的多台
	/*
	*
	template<class _Ret,
	class _Rx,
	class _Farg0,
	class _Arg0> inline
	typename enable_if<!is_same<_Ret, _Rx>::value,
		_Bind<true, _Ret, _Pmd_wrap<_Rx _Farg0::*, _Rx, _Farg0>, _Arg0>
			>::type
		bind(_Rx _Farg0::* const _Pmd, _Arg0&& _A0)
	{	// bind a wrapped member object pointer
	return (_Bind<true, _Ret,
		_Pmd_wrap<_Rx _Farg0::*, _Rx, _Farg0>, _Arg0>(
		_Pmd_wrap<_Rx _Farg0::*, _Rx, _Farg0>(_Pmd),
			_STD forward<_Arg0>(_A0)));
	}
	*
	*
	*/
	std::function<bool(int)> printInt = std::bind(&B::print,pa,std::placeholders::_1);//
	std::function<bool(int)> printInt2 = std::bind(&A::print,pa,std::placeholders::_1);
	printInt(1000);
	printInt2(1002);

	typedef std::function<bool(int)> FP;

	FP t_fp = FP(print);

	t_fp(12);
	cout<<endl;

	//找出不小于12的数据
	std::vector<int> iv(ia,ia+6);
	std::copy_if(iv.begin(),iv.end(),out_it,std::not1(std::bind2nd(std::less<int>(),12)));

	//cout<< std::count_if(ia,ia+6,std::not1(std::bind(f1,12)) )<<endl;

	cout<<endl;

	int nums = std::count_if(
		iv.begin(),iv.end(),
		std::bind(
			std::logical_and<bool>(),
			std::bind(std::less<int>(),std::placeholders::_1,30),
			std::bind(std::greater<int>(),std::placeholders::_1,12)
			)
		);
	cout<<"(12,30):"<<nums<<endl;
	//在循环内部讲执行这样一句代码:_Pred(*first)。_Pred就是函数对象std::bind(std::less<int>(),std::placeholders::_1,12)产生的对象
	int nums2= std::count_if(iv.begin(),iv.end(),std::bind(std::less<int>(),std::placeholders::_1,12));
	cout<<"(-,12):"<<nums2<<endl;

	//使用迭代器输出所以数据
	std::copy(iv.begin(),iv.end(),out_it);
	cout<<endl;

	//使用函数名输出
	std::for_each(iv.begin(),iv.end(),print);//类中的函数操作保存在某个位置,我要阅读其他书籍才知道。仿函数对象指的一个仿函数对象,普通函数对象就是函数名,待续
	cout<<endl;

	//使用仿函数对象输出,需要通过指针处理,因为stl函数库的定义使用的模板,不进行类型检查(同时ide也无法完成成员提醒,因为未特化不存在改类型类型相关的代码),
	//只要存在operator()重载即可通过编译。如果使用pa传值,内部调用的()操作符,但是原生指针类型没有进行operator()操作的,会编译报错。
	std::for_each(iv.begin(),iv.end(),(*pa));
	cout<<endl;

	FunPtr fp1 = print; //函数指针和函数名是同一个东西?
	fp1(10);
	cout<<endl;

	//使用函数指针输出
	std::for_each(iv.begin(),iv.end(),fp1);//类中的函数操作保存在某个位置,我要阅读其他书籍才知道。仿函数对象指的一个仿函数对象,普通函数对象就是函数名,待续
	cout<<endl;

	//修饰过一般函数的STL算法,这个东西还没看,一点都不懂
	std::for_each(iv.begin(),iv.end(),std::ptr_fun(fp1));//使用包装好的函数最后调用结构std::ptr_fun(*begin()),里面执行的则是fp1(*begin())
	cout<<endl;

//	#define _BIND_IMPLICIT1( //	TEMPLATE_LIST1, PADDING_LIST1, LIST1, COMMA1, //	TEMPLATE_LIST2, PADDING_LIST2, LIST2, COMMA2) //template<class _Rx //	COMMA1 LIST1(_CLASS_TYPE) //	COMMA2 LIST2(_CLASS_TYPEX)> inline //	_Bind<true, _Rx, _Rx (* const)(LIST1(_TYPE)) COMMA2 LIST2(_TYPEX)> //		bind(_Rx (*_Pfx)(LIST1(_TYPE)) COMMA2 LIST2(_TYPEX_REFREF_ARG)) //	{	/* bind a function pointer */ //	return (_Bind<true, _Rx, _Rx (* const)(LIST1(_TYPE)) //		COMMA2 LIST2(_TYPEX)>(_Pfx COMMA2 LIST2(_FORWARD_ARGX))); //	}
	//注:COMMA:逗号,传参使用的是_TYPEX_REFREF_ARG
	/*
	1: #define _TYPEX_REFREF(NUM)			_VAR_TYPEX(NUM)&&

	2:#define _FORWARD_ARGX(NUM)		_STD forward<_VAR_TYPEX(NUM)>(_VAR_VALX(NUM))

	_VAR_TYPEX 是右值类型,所以再调用跳转的过程中,估计发生了的事情:n被转化为右值类型然后产生了某个副本,

	正解:std::forward<T>(u) 有两个参数:T 与 u。当T为左值引用类型时,u将被转换为T类型的左值,否则u将被转换为T类型右值。
	如此定义std::forward是为了在使用右值引用参数的函数模板中解决参数的完美转发问题。

	*/

	int n = 0;
	std::bind(inc,n)();//源码中使用的是
	print(n);//还是0;

	std::bind(inc,std::ref(n))();
	print(n);//终于是1啦。

	Int t1(3),t2(7),t3(20),t4(14),t5(26);

	std::vector<Int> vInt2;
	vInt2.push_back(t1); //cocos2dx中的testcpp有段反射代码,可以考虑用上来,短期险熟悉C++11的stl
	vInt2.push_back(t2);
	vInt2.push_back(t3);
	vInt2.push_back(t4);
	vInt2.push_back(t5);

//mem_fun则是质变算法。当for_each
//两者区别:
//mem_fun_ref的作用和用法跟mem_fun一样,唯一的不同就是:
//当容器中存放的是对象实体的时候用mem_fun_ref,
//当容器中存放的是对象的指针的时候用mem_fun。

	//error C3867: “Int::print1”: 函数调用缺少参数列表;请使用“&Int::print1”创建指向成员的指针
	std::for_each(vInt2.begin(),vInt2.end(),std::mem_fun_ref(&Int::print1));//如果使用非指向函数名的指针,会报错
	cout<<endl;
	;

	std::for_each(vInt2.begin(),vInt2.end(),std::bind(Int::print3,std::placeholders::_1));//只要保证函数接口的正确性就可以,std::bind构造函数的首参数一定是提供operator()的对象,可以是仿函数和函数名,使用静态是因为由函数操作对象,而不是访问对象的操作

	//std::for_each(vInt2.begin(),vInt2.end(),std::mem_fun_ref(&std::bind(Int::print3,std::placeholders::_1)));

	cout<<endl;

	;

	std::for_each(vInt2.begin(),vInt2.end(),std::bind(std::plus<Int>(),std::placeholders::_1,Int(3)));
	std::for_each(vInt2.begin(),vInt2.end(),std::mem_fun_ref(&Int::print1));//如果使用非指向函数名的指针,会报错
	cout<<endl;

	//暂时无法使用stlmem_fun_ref实现多参数操作
	//std::for_each(vInt2.begin(),vInt2.end(),std::bind(,std::placeholders::_1,Int(3)));
	//std::for_each(vInt2.begin(),vInt2.end(),std::mem_fun_ref(&Int::print1));//如果使用非指向函数名的指针,会报错
	//cout<<endl;

	return 0;
}
时间: 2024-10-13 00:25:04

STL C++ std::bind操作例子,仿函数操作配合算法库操作的相关文章

Jsonp和java操作例子

介绍JSONP之前,先简单的介绍一些JSON.JSON是JavaScript Object Notation的缩写,是一种轻量的.可读的基于文本的数据交换开放标准.源于JavsScript编程语言中对简单数据结构和关联数组的展示功能.它是仅含有数据对和简单括号结构的纯文本,因此可通过许多途径进行JSON消息的传递. 1. JSONP定义    JSONP是英文JSON with Padding的缩写,是一个非官方的协议.它允许在服务器端生成script tags返回至客户端,通过javascri

dom操作例子

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <script src="Scripts/jquery-1

jquery api 常见api 效果操作例子

addClass_removeClass_toggleClass_hasClass.html 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 <html> 3 <head> 4 <title>method_1.html</title> 5 <meta http-equiv="content-type" conten

[Spark][Python]RDD flatMap 操作例子

RDD flatMap 操作例子: flatMap,对原RDD的每个元素(行)执行函数操作,然后把每行都“拍扁” [[email protected] ~]$ hdfs dfs -put cats.txt[[email protected] ~]$ hdfs dfa -cat cats.txtError: Could not find or load main class dfa[[email protected] ~]$ hdfs dfs -cat cats.txtThe cat on the

jquery api 常见api 元素操作例子

append_prepend.html 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 <html> 3 <head> 4 <title>method_1.html</title> 5 <meta http-equiv="content-type" content="text/html; charset=

DataNucleus之JDO操作例子

JDO(Java Data Object )是Java对象持久化的新的规范,也是一个用于存取某种数据仓库中的对象的标准化API.注意JDO是一种规范,而不是一个产品.而DataNucleus正是实现JDO规范的产品之一,JDO实现产品还有FOStore.JPOX等.当然DataNucleus不仅实现了JDO规范,还实现了JPA(java另一持久化规范),也就是说有了DataNucleus,你既可以选择JDO API,也可以选择JPA API进行持久化操作. 现在DataNucleus官网上主要推

springboot数据库操作及事物管理操作例子

一.配置文件 application.yml 1 spring: 2 profiles: 3 active: dev 4 datasource: 5 driver-class-name: com.mysql.jdbc.Driver 6 url: jdbc:mysql://127.0.0.1:3306/dbgirl 7 username: root 8 password: 123456 9 jpa: 10 hibernate: 11 ddl-auto: update 12 show-sql: tr

std::bind接口与实现

前言 最近想起半年前鸽下来的Haskell,重温了一下忘得精光的语法,读了几个示例程序,挺带感的,于是函数式编程的草就种得更深了.又去Google了一下C++与FP,找到了一份近乎完美的讲义,然后被带到C++20的ranges library,对即将发布的C++20满怀憧憬.此时,我猛然间意识到,看别人做,觉得自己也能做好,在游戏界叫云玩家,在编程界就叫云程序员啊! 不行,得找点事干.想起同样被我鸽了很久的<functional>系列,刚好与函数式编程搭点边,就动笔写吧!这就是本文的来历. 找

c++11特性与cocos2d-x 3.0之std::bind与std::function

昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 cocos2d-x 3.0rc0 差别还是相当大的. 发现Label这一个控件,3.0就比rc0版本多了一个创建函数,更为关键的是3.0内的Label锚点是在ccp(0.5,0.5),而一直3.0rc0是ccp(0,0). 累觉不爱.尽管cocos2d-x改变太快,兼容性一次次的暴露出不足,但是,总归是向好的方向进行.于是下载了3.0来玩玩~ cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码: