/**
 * @class array
It is possible to declare array variables with the array identifier followed by the type of the elements within angle brackets.

Example:

	@code{.cpp}
	  array<int> a, b, c;
	  array<Foo@> d;
	@endcode  

a, b, and c are now arrays of integers, and d is an array of handles to objects of the Foo type.

When declaring arrays it is possible to define the initial size of the array by passing the length as a parameter to the constructor. The elements can also be individually initialized by specifying an initialization list. Example:

	@code{.cpp}
	  array<int> a;           // A zero-length array of integers
	  array<int> b(3);        // An array of integers with 3 elements
	  array<int> c(3, 1);     // An array of integers with 3 elements, all set to 1 by default
	  array<int> d = {5,6,7}; // An array of integers with 3 elements with specific values
	@endcode  

Multidimensional arrays are supported as arrays of arrays, for example:

	@code{.cpp}
	  array<array<int>> a;                     // An empty array of arrays of integers
	  array<array<int>> b = {{1,2},{3,4}}      // A 2 by 2 array with initialized values
	  array<array<int>> c(10, array<int>(10)); // A 10 by 10 array of integers with uninitialized values
	@endcode  

Each element in the array is accessed with the indexing operator. The indices are zero based, i.e. the range of valid indices are from 0 to length - 1.

	@code{.cpp}
		a[0] = some_value;
	@endcode  

When the array stores handles the elements are assigned using the handle assignment.

	@code{.cpp}
	  // Declare an array with initial length 1
	  array<Foo@> arr(1);
	@endcode  

	@code{.cpp}
		// Set the first element to point to a new instance of Foo
		@arr[0] = Foo();
	@endcode  

Arrays can also be created and initialized within expressions as anonymous objects.

	@code{.cpp}
	  // Call a function that expects an array of integers as input
	  foo(array<int> = {1,2,3,4});
	@endcode  

 */
 
template <class T>
class array
{
public:
	T& operator[] (const int index);
	
	/**
	* @brief Returns the length of the array.
	*/
	uint length();
	
	/**
	* @brief Sets the new length of the array.
	*/
	void resize(uint size);
	
	/**
	* @brief Reverses the order of the elements in the array.
	*/
	void reverse();
	
	/**
	* @brief Inserts a new element into the array at the specified index.
	*/
	void insertAt(uint index, const T& in value);
	
	/**
	* @brief Inserts another array of elements into the array at the specified index.
	*/
	void insertAt(uint index, const array<T>& value);
	
	/**
	* @brief Appends an element at the end of the array.
	*/
	void insertLast(const T& in value);
	
	/**
	* @brief Removes the element at the specified index.
	*/
	void removeAt(uint index);
	
	/**
	* @brief Removes the last element of the array.
	*/
	void removeLast();
	
	/**
	* @brief Removes count elements starting from start.
	*/
	void removeRange(uint start, uint count);
	
	/**
	* @brief Sorts the elements in the array in ascending order. For object types, this will use the type's opCmp method.
	*/
	void sortAsc();
	
	/**
	* @brief Sorts only the elements starting at index \a startAt and the following \a count elements in the array in ascending order. For object types, this will use the type's opCmp method.
	*/
	void sortAsc(uint startAt, uint count);
	
	/**
	* @brief Sorts the elements in the array in descending order. For object types, this will use the type's opCmp method.
	*/
	void sortDesc();
	
	/**
	* @brief Sorts only the elements starting at index \a startAt and the following \a count elements in the array in descending order. For object types, this will use the type's opCmp method.
	*/
	void sortDesc(uint startAt, uint count);
	
	/**
	* @brief Returns the index of the first element that has the same value as the wanted value.
	* For object types, this will use the type's opEquals or opCmp method to compare the value. For arrays of handles any null handle will be skipped.
	* If no match is found will return a negative value.
	*/
	int find(const T& in value);
	
	/**
	* @brief Returns the index of the first element that has the same value as the wanted value.
	* For object types, this will use the type's opEquals or opCmp method to compare the value. For arrays of handles any null handle will be skipped.
	* If no match is found will return a negative value.
	*/
	int find(uint startAt, const T& in value);
	
	/**
	* @brief Searches for a matching address. These are especially useful for arrays of handles where specific instances of objects are desired, and not just objects that happen to have equal value.
	* If no match is found will return a negative value.
	*/
	int findByRef(const T& in value);
	
	/**
	* @brief Searches for a matching address. These are especially useful for arrays of handles where specific instances of objects are desired, and not just objects that happen to have equal value.
	* If no match is found will return a negative value.
	*/
	int findByRef(uint startAt, const T& in value);
};
