/*****************************************************************************
 * $Id: ArrayOperatorSubscript.cc,v 1.3 2006/07/02 17:05:24 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Not really a test, rather, this was an experiment to try to add
 *          uninitialized element checking to the Array class but it doesn't
 *          reveal any way to tell if operator[] is reading or writing an element.
 *
 *          Excluded from Makefile since this isn't a useful test.   
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#define TESTING 1
#include <assert.h>
#include <iostream>
using namespace std;

typedef unsigned int uint;
#define DEBUG2_CODE(code) code

////////////////////////////////////////////
/// @brief Array class.  Array size is fixed.
/// @remarks Tested at gfx/tests/basic_types.cc.
template<uint cnt, typename T=int>
struct Array
{
	typedef T type;

	Array( void ) { }

	/// Construct all elements with the same value.
	Array( T val )
	{
		Fill( val );
	}

	/// Copy constructor.
	Array( const Array<cnt,T>& src )
	{
		*this = src;
	}

	/// @return Amount of elements.
	uint GetCnt( void ) const
	{
		return cnt;
	}

	/// Assign every element the same value.
	void Fill( T val )
	{
		for ( uint i = 0; i < cnt; ++i )
			mArray[i] = val;
	}

	T& operator[]( uint i )
	{
		cerr << "operator (non-const) called" << endl;
		DEBUG2_CODE( assert( i < cnt ) );
		return mArray[i];
	}

	const T& operator[]( uint i ) const
	{
		cerr << "operator (const) called" << endl;
		DEBUG2_CODE( assert( i < cnt ) );
		return mArray[i];
	}

	/// Amazing that a C++ compiler will accept how this type is written.
	Array<cnt,T>& operator=( const Array<cnt,T>& src )
	{
		for ( uint i = 0; i < cnt; ++i )
			mArray[i] = src.mArray[i];	// assign
		return *this;
	}

	bool operator==( const Array<cnt,T>& src )
	{
		for ( uint i = 0; i < cnt; ++i )
			if ( mArray[i] != src.mArray[i] ) return false; // different
		return true; // all elements equal
	}

	bool operator!=( const Array<cnt,T>& src )
	{
		// Same as operator==() but retvals opposite.
		for ( uint i = 0; i < cnt; ++i )
			if ( mArray[i] != src.mArray[i] ) return true; // different
		return false; // all elements equal
	}

	T	mArray[cnt];
};

int main( int argc, char** argv )
{
	// Bad bad -- access uninitialized element.
	// g++ 2.9 causes operator[] non-const to be called.
	Array<2> a;
	int x = a[0];

	// const operator[] called this time.
	const Array<2> a2;
	int x2 = a2[1];
}
