#include <memory>

/* 
 * Auto-deleting arrays.
 * See also http://www.gotw.ca/gotw/042.htm
 */


// A shim to insert between arrays and std::auto_ptr
template <typename T>
class array_deleter {
public:
	array_deleter(T *a) : array(a) {}
	~array_deleter()               { delete[] array;  }
	T* get()                 const { return array;    }
	T& operator[](int i)     const { return array[i]; }
private:
	T *array;
};

// Syntax candy for std::auto_ptr<array_deleter<T> >
template <typename T>
class auto_array : public std::auto_ptr<array_deleter<T> >
{
public:
	auto_array(T *t = 0) :
		std::auto_ptr<array_deleter<T> >(new array_deleter<T>(t)) {}

	T* get() const
	{
		return std::auto_ptr<array_deleter<T> >::get()->get();
	}

	T& operator[](int i) const
	{
		return std::auto_ptr<array_deleter<T> >::get()->get()[i];
	}
};




#include <iostream>

class Noisy
{
public:
	Noisy()  { std::cout << "Constructed" << std::endl; }
	~Noisy() { std::cout << "Destructed"  << std::endl; }
};

int main()
{
	std::cout << "With auto_ptr:" << std::endl;
	{
		std::auto_ptr<Noisy> n(new Noisy[2]);
		// might crash here
	}
	std::cout << "With auto_array:" << std::endl;
	{
		auto_array<Noisy> n(new Noisy[2]);
	}
}

/* Typical output:

With auto_ptr:
Constructed
Constructed
Destructed
<may crash here, depending upon your C++ runtime implementation>
With auto_array:
Constructed
Constructed
Destructed
Destructed

*/

