/*Orion Lawlor's Simple C++ Examples, olawlor@acm.org
Shows how to overload a bunch of cast operators for a class.
*/
#include <stdio.h>

template <class T>
class msa;

/**
  Mediates access to a single item in the MSA array.
*/
template <class T>
class MSA_ValueHandle {
private:
	msa<T> &m;
	int idx;
	T val;
public:
	MSA_ValueHandle(msa<T> &m_,int idx_) 
		:m(m_), idx(idx_), val(idx) {}
	
	/**
	  Cast-to-output operator.  This is called 
	  on all sorts of read operations, including:
	      ... = x;
	      ... x * ...;
	      foo(...,x,...);
	*/
	operator T () {
		printf("msa::read(%d)\n",idx);
		return val;
	}
	
	/**
	   Assignment operator.  This is *only* called
	   when assigning a value to our object, like
	   	x = ...;
	*/
	const T &operator=(const T &src) {
		printf("msa::assign(%d)\n",idx);
		return val;
	}
	
	/**
	   Assignment operator.  This is *only* called
	   when using += to assign a value to our object, like:
	   	x += ...;
	*/
	const T &operator+=(const T &src) {
		printf("msa::accumulate(%d)\n",idx);
		return val;
	}
};

/**
  Stores a whole list of objects in an MSA array.
*/
template <class T>
class msa {
public:
	MSA_ValueHandle<T> operator[](int i) const 
		{return MSA_ValueHandle<T>(*(msa<T> *)this,i);}
};

int main()
{
	msa<double> m;
	double x=m[1];
	m[2]=x+m[12];
	m[3]+=x;
	m[4]+=m[14];
	
	return 0;
}
/*<@>
<@> ******** Program output: ********
<@> msa::read(1)
<@> msa::read(12)
<@> msa::assign(2)
<@> msa::accumulate(3)
<@> msa::read(14)
<@> msa::accumulate(4)
<@> */
