/************************************************************************************/
/* Jakub Sękowski H5ISI boost::operators					    */
/* Biblioteka pomaga programiście w implementacji przeciążonych operatorów klas	    */
/* przez implementację szeregu klas bazowych specjalizujących sie w wykonaniu	    */
/* charakterystycznych operacj. Wymaga ona jednak od użytkownika przeciążenia	    */ 
/* podstawowego dla danej klasy bazowej operatora.				    */
/* np. Za pomocą operatora "<" można zapisać operatory: "<=", ">=" oraz ">".	    */
/* Aby znacznie nie powiększać zbioru operatorów przeciążonych dla klasy mamy	    */
/* możliwość wyprowadzenia naszej klasy z szablonowej klasy bazowej		    */
/* "less_than_comparable". Teraz musimy juz zaimplementować tylko operator< - resztę*/
/* implementuje nasza klasa bazowa						    */
/************************************************************************************/

/*    Przykład    */
#include <iostream>
#include <boost/operators.hpp>

class some_class: boost::less_than_comparable<some_class>{

	int data;

public:
	some_class(int num):data(num){
	}
	bool less_than(const some_class& lhs)const{
		return data<lhs.data;
	}
//	friend bool operator<(const some_class& a, const some_class& b){
//		return a.data<b.data;
//	}
};

bool operator<(const some_class& lhs, const some_class& rhs){
	return lhs.less_than(rhs);
}
int main(){

	some_class ob1(3);
	some_class ob2(5);

	std::cout<<(ob1<ob2);
	std::cout<<(ob1>ob2);
	std::cout<<(ob1<=ob2);
	std::cout<<(ob1>=ob2);
	return 0;
}
/********************************************************************************************************/
/*		Wynikiem działania programu jest oczywiście: 1010 					*/
/* Zamiast implementacji funkcji less_than możemy dodać do metod klasy zaprzyjaźnioną funkcję operator<	*/
/*  (zakomentowane), co jest jak najbardziej poprawną implementacją.					*/
/********************************************************************************************************/
/* Poza less_than_comparable do dyspozycji mamy:							*/
/* klasa bazowa		opearacje zaimplementowane:	 	wymagane od klasy pochodnej:		*/
/* equality_comparable	bool operator==(const T&, const T&)	bool operator==(const T&, const T&)	*/
/* 			bool operator!=(const T&, const T&)						*/
/* addable		T operator+ (const T&, const T&)	T operator+=(const T&)			*/
/* 			T operator+=(const T&)								*/
/* subtractable		T operator- (const T&, const T&)	T operator-=(const T&)			*/
/* 			T operator-=(const T&)								*/
/* orable		T operator| (const T&, const T&)	T operator|=(const T&, const T&)	*/
/* 			T operator|=(const T&, const T&)						*/
/* andable		T operator& (const T&, const T&)	T operator&=(const T&, const T&)	*/
/* 			T operator&=(const T&, const T&)						*/
/* incrementable	T& operator++(T&)			T& operator++(T&)			*/
/* 			T operator++(T&, int)								*/
/* decrementable	T& operator--(T&)			T& operator--(T&)			*/
/* 			T operator--(T&, int)								*/
/* equivalent		T& operator< (T&)			T& operator<(const T&, const &T)	*/
/* 			T operator++(T&, int)								*/
/* dereferenceable	R operator->() const			R* operator*() const			*/
/* 			R operator* () const								*/
/* 			(T - typ operandu, R - typ referencji T, P -typ wskaźnika T)			*/
/* indexable		R operator[](D) const			R operator+	(const T&, D)		*/
/* 			R operator+ (const T&, D)							*/
/* 				(D - typ wartości indeksujących)					*/
/********************************************************************************************************/
/* To są tylko podstawowe klasy, istnieje dużo więcej gromadzących w sobie takie operacje jak xor lub   */ 
/* mod. Istnieją także klasy grupujące w/w klasy.							*/
/* np:													*/
/* totaly_ordered zawiera: less_than_comparable i equality_comparable					*/
/* additive:				addable i subtractable						*/
/* itp, itd.....  więcej szczegółów: http://www.boost.org/						*/
/*													*/
/* Możemy dizedziczyć wielobazowo:									*/
/* class some_class: boost::less_than_comparable<some_class>,						*/
/* 			      boost::equivalent<some_class>{						*/
/* }													*/
/*													*/
/* Należy zwrócić uwagę na rozrastanie się klas. Niektóre kompilatory nieradzą sobie z optymalnym	*/
/* dziedziczeniem wielobazowym, nadmiernie zwiększając rozmiar obiektów klas pochodnych kopiując	*/
/* wielokrotnie początkowe klasy bazowe. Problem ten rozwiązany jest za pomocą łańcucha dziedziczenia	*/ 
/* jednobazowego. Każdy szablon funkcji bazowej w boost::operators może przyjmować opcjonalnie poza	*/
/* klasą pochodną, klasę bazową po której ma dziedziczyć. W ten sposób z klas bazowych możemy utwożyć	*/
/* łańcuch w którym każda klasa będzie wskazywała poprzednika w łańcuchu dziedziczenia.			*/
/* Dobrym przykladem są typy atytmetyczne, od których można wymagać implementacji wielu operatorów.	*/
/* ******************************************************************************************************/

/*		Przykład		*/

#include<iostream>
#include<boost/operators.hpp>

template<class T>
class some_class2:
	boost::addable<some_class2<T>, 
		boost::subtractable<some_class2<T>,
			boost::less_than_comparable<some_class2<T>,
				boost::equality_comparable<some_class2<T>>
	>>>
	{
	public:
		some_class2():t(0){}
		some_class2(T t_):t(t_){}
		T get(){
			return t;
		}

		// dla less_than_comparable
		friend bool operator<(const some_class2<T>& lhs, const some_class2<T>& rhs){
			return lhs.t<rhs.t;
		}
		
		//dla equality_comparable
		friend bool operator==(const some_class2<T>& lhs, const some_class2<T>& rhs){
			return lhs.t==rhs.t;
		}

		//dla addable
		some_class2<T>& operator+=(const some_class2<T>& other){
			t+=other.t;
			return *this;
		}

		//dla subtractable
		some_class2<T>& operator-=(const some_class2<T>& other){
			t-=other.t;
			return *this;
		}

	private:
		T t;
	};

/*********************************************************************************************************/
/* Taki zapis deklaracji klasy, gdzie jako 2 argument szablonu klasy podajemy klasę bazową zapewnia	 */
/* odpowiedni łańcuch dziedziczenia oraz zawarcie w nim wszystkich niezbednych klas. Zauważmy także, że  */
/* zapisując implementację przeciążenia 4 operatorów, mamy dostęp do 10, modyfikując tylko deklarację    */
/* klasy. Zmniejsza to możliwość popełnienia błędu przez programistę. Pamiętajmy, iż mamy dostęp do typów*/ 
/* złożonych, co sprawia, że naszą deklarację klasy można sprowadzić do postaci:			 */
/*********************************************************************************************************/

template<class T>
class some_class2:
	boost::additive<some_class2<T>, 
		boost::totally_ordered<some_class2<T>>>

/*********************************************************************************************************/
/* Jak widać jest to rozwiązanie dużo krótsze co sprawia, że tródniej jest się pomylić.			 */
/* Operators posiada także implementację klas zajmujących się operatorami indeksowania i dereferencji	 */
/* przydatne głównie w klasach zachowujących się podobnie do iteratorów. Zasada działania analogiczna    */
/* do poprzednich przykładów.										 */
/*********************************************************************************************************/