Click here to Skip to main content
15,892,737 members
Articles / Desktop Programming / MFC

MFC - Multiple inheritance and serialization

Rate me:
Please Sign up or sign in to vote.
4.80/5 (34 votes)
29 Oct 2003CPOL14 min read 163.8K   4.2K   73  
Describing a solution to allow namespaces, multiple inheritance, and serialization in an MFC program
#pragma once

// In this header some operator definitions.
//		They are different from the STL <utility> defined ones, because they are AFXAPI (that is _stdcall, instead of _cdecl).
//		CString operators don�t conflict with these operators (they appear to be specializations) but conflict with the STL ones because of the different calling convenction
// 

namespace GE_{namespace Mfc{
}}

// define in case it is not yet defined
#ifndef AFXAPI
#define AFXAPI __stdcall
#endif

namespace GE_{ namespace Operators
{
	using namespace GE_::Mfc; //required for some GE_::Mfc namespace operators

	//comparisons, all in term of == and <

	template <class T, class U>
	bool AFXAPI operator!=(const T& t, const U& u)
	{	return !(t==u);	};

	template <class T, class U>
	bool AFXAPI operator<=(const T& t, const U& u)
	{	return (t<u)||(t==u);	};

	template <class T, class U>
	bool AFXAPI operator>=(const T& t, const U& u)
	{	return (u<=t);	};

	template <class T, class U>
	bool AFXAPI operator>(const T& t, const U& u)
	{	return (u<t);	};

	
	// MAX and Min functions (not macros)

	template <class T>
	const T& AFXAPI Max(const T& t, const T& u)
	{	return (t<u)? u: t;	};

	template <class T>
	const T& AFXAPI Min(const T& t, const T& u)
	{	return (t<u)? t: u;	};

	
	// Sampling to Max or Min: t=u if u> or <t.

	template <class T, class U>
	T& AFXAPI SampleMax(T& t, const U& u)
	{	if (t<u) t=u; return t; };

	template <class T, class U>
	T& AFXAPI SampleMin(T& t, const U& u)
	{	if (u<t) t=u; return t; };



	// Clipping: t=u if u<t

	template <class T, class U>
	T& AFXAPI ClipMax(T& t, const U& u)
	{	if (u<t) t=u; return t; };

	template <class T, class U>
	T& AFXAPI ClipMin(T& t, const U& u)
	{	if (t<u) t=u; return t; };

	
	// Swap two values
	
	template <class T>
	void AFXAPI Swap(T& a, T& b)
	{ T c(a); a=b; b=c;	};


	// make t to stay between min and max

	template <class T>
	bool AFXAPI Limit(T& t, const T& min, const T& max)
	{
		bool b = false;
		if (t<min)
			b = true, t=min;
		if(min<max && max<t)
			b = true, t=max;
		if(max < min)
			b = true, t = min;
		return b;
	}

	
	// make always a < b by swapping if needed
	
	template <class T>
	bool AFXAPI Sort(T& a, T& b)
	{
		if (a<b) return true;
		Swap(a,b);
		return false;
	}


	// check various type of ranges

	template <class T, class U, class V>
	bool IsInRangeLR(const T& t, const U& u, const V& v)
	{	return u<=t && t<=v;	}

	template <class T, class U, class V>
	bool IsInRangeL_(const T& t, const U& u, const V& v)
	{	return u<=t && t<v;	}

	template <class T, class U, class V>
	bool IsInRange_R(const T& t, const U& u, const V& v)
	{	return u<t && t<=v;	}

	template <class T, class U, class V>
	bool IsInRange__(const T& t, const U& u, const V& v)
	{	return u<t && t<v;	}

	template <class T, class U, class V>
	bool IsInGapL_(const T& t, const U& val, const V& size)
	{	return val<=t && t<val+size;	}

	template <class T, class U, class V>
	bool IsInGap_R(const T& t, const U& val, const V& size)
	{	return val<t-size && t<=val;	}

	template <class T, class U, class V>
	bool IsInGapLR(const T& t, const U& val, const V& size)
	{	return val<=t-size && t<=val+size;	}

	template <class T, class U, class V>
	bool IsInGap__(const T& t, const U& val, const V& size)
	{	return val<t-size && t<val+size;	}


	// define operator i term of their correspondent assignments

	template <class T, class U>
	T AFXAPI operator+(const T& t, const U& u)
	{	T r(t); r+=u; return r;	}

	template <class T, class U>
	T AFXAPI operator-(const T& t, const U& u)
	{	T r(t); r-=u; return r;	}

	template <class T, class U>
	T AFXAPI operator*(const T& t, const U& u)
	{	T r(t); r*=u; return r;	}

	template <class T, class U>
	T AFXAPI operator/(const T& t, const U& u)
	{	T r(t); r/=u; return r;	}

	template <class T, class U>
	T AFXAPI operator%(const T& t, const U& u)
	{	T r(t); r%=u; return r;	}

	template <class T, class U>
	T AFXAPI operator&(const T& t, const U& u)
	{	T r(t); r&=u; return r;	}

	template <class T, class U>
	T AFXAPI operator|(const T& t, const U& u)
	{	T r(t); r|=u; return r;	}

	template <class T, class U>
	T AFXAPI operator^(const T& t, const U& u)
	{	T r(t); r^=u; return r;	}

	
    //increment a passed counter, and decrement on destruction
	// typical use:
	//	{
	//		SLockCount lock; lock(avariable);
	//		// do some action
	//	}
	//		"avariable" decremented reacing this brace

	struct SLockCount
	{
		int* pLocks;
		int Lock() {if(pLocks) (*pLocks)++; return *pLocks;}
		int UnLock() {if(pLocks) (*pLocks)--; return *pLocks;}
		int Lock(int& b) {pLocks = &b; return Lock();}
		SLockCount() {pLocks = NULL;}
		~SLockCount() {UnLock();}
	};

	
	// CMulticalstCall is a list of referred items, that calls items member functions in turn.
	// The list can be abjusted on call by overriding UpdateMembersList

	template<class I>
	class CMulticastCall:
		public std::list<I*>
	{
	public:
		//called by "Call" functions, to give a chance to update the list
		virtual void UpdateMembersList() {;} //does nothing

		void Call(void (I::*pfnVoid)())
		{	UpdateMembersList(); for(iterator i = begin(); i!=end(); i++) ((*i)->*pfnVoid)();	}
		
		template<class A>
		void Call(void (I::*pfn1)(A), A a)
		{	UpdateMembersList(); for(iterator i = begin(); i!=end(); i++) ((*i)->*pfn1)(a);	}
		
		template<class A, class B>
		void Call(void (I::*pfn2)(A,B), A a, B b)
		{	UpdateMembersList(); for(iterator i = begin(); i!=end(); i++) ((*i)->*pfn2)(a,b);	}
		
		template<class A, class B, class C>
		void Call(void (I::*pfn3)(A,B,C), A a, B b, C c)
		{	UpdateMembersList(); for(iterator i = begin(); i!=end(); i++) ((*i)->*pfn3)(a,b,c);	}
		
		template<class A, class B, class C, class D>
		void Call(void (I::*pfn4)(A,B,C,D), A a, B b, C c, D d)
		{	UpdateMembersList(); for(iterator i = begin(); i!=end(); i++) ((*i)->*pfn4)(a,b,c,d);	}
		
	};




	// STemAssign assign a value on construction and restore the previous value on destruction
	// Typical use:
	// {
	//		STempAssign<int> ta(a_int_member, a_value);
	// 		//  do some actions
	// 		// �
	// }
	// //  variable restored at this brace


	template<class V>
	class STempAssign
	{
	private:
		V* _pVar;
		V _prevVal;
	public:
		STempAssign(V& var, const V& val)
		{
			_pVar = &var;
			_prevVal = var;
			var = val;
		}
		~STempAssign()
		{
			*_pVar = _prevVal;
		}
	};
}}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Italy Italy
Born and living in Milan (Italy), I'm an engineer in electronics actually working in the ICT department of an important oil/gas & energy company as responsible for planning and engineering of ICT infrastructures.
Interested in programming since the '70s, today I still define architectures for the ICT, deploying dedicated specific client application for engineering purposes, working with C++, MFC, STL, and recently also C# and D.

Comments and Discussions