gnu編譯C++11,最好與win32公用代碼

看makefile:

#jingz's first file to test makeFile
allTarget:stdafx_target 11_12_target
	g++ stdafx.o functor-adapter_p431.o -o functor-adapter_p431.exe
#remove the object files
	rm -rf stdafx.o functor-adapter_p431.o
#complie the cpps into objects
stdafx_target:
	g++ -std=c++11 -c stdafx.cpp -o stdafx.o
11_12_target:
	g++ -std=c++11 -c functor-adapter_p431.cpp -o functor-adapter_p431.o


平時使用vs、xcode等ide,老是忽略預編譯命令,還是得吃

-std=c++11 C++11的預編譯定義,因爲gnu默認關閉C++11特性


比較多家的編譯器是有所區別的,根據實際情況使用預編譯處理。

1)比如tchar相關:

#ifdef WIN32
#include "targetver.h"
#include <tchar.h>
#endif

如果是cocos2dx,則可以使用CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 這類似預編譯定義處理跨平臺的兼容問題
// 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<<"]";
	}
	
	void addNum(int j)
	{
		m_i+=j;
	}


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;
}


#ifdef WIN32
int _tmain(int argc, _TCHAR* argv[])
#else
int main(int argc, char* argv[])
#endif
{
	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;


	std::vector<int> iv3;
	std::copy(iv.begin(),iv.end(),std::back_inserter(iv3));//back_inserter 是返回迭代器的函數,就像一個適配器。名爲迭代器適配器,和本例子的函數適配器相仿,用於不同的場景

	std::for_each(iv3.begin(),iv3.end(),print);//如果使用非指向函數名的指針,會報錯
	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::mem_fun_ref(&Int::addNum),std::placeholders::_1,3));
	std::for_each(vInt2.begin(),vInt2.end(),std::mem_fun_ref(&Int::print1));//如果使用非指向函數名的指針,會報錯
	cout<<endl;


	
	


	std::istream_iterator<int> in_it(cin),eos;//這裏有個bug,必須要用多線程解決。程序主線程啓動讀寫,等待輸入操作中斷置位,vs_stl不提供切換操作。MS的STL中insert_iterator採用主動讀取數據的操作,主線程將中斷讀取操作中。這會導致一個嚴重的bug,即構建某個IO操作時提前完成了數據操作,而這可能不是我們期望的。

	std::function<bool(int)> f1 = std::bind(std::less<int>(),std::placeholders::_1,13);

	cout<<"less(3,13):"<<f1(3)<<endl;

	while (!(in_it==eos))
	{
		cout<<*in_it;
		cout<<endl;
		++in_it;
	}


	

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章