// http://ragestorm.net 2009

#include <windows.h>

template<bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert <true> { }; 
#define BOOST_STATIC_ASSERT(e) (CompileTimeAssert<(e) != 0>()) 

class MyException {
public:
	MyException(char*) { }
};

template <class T> class AutoResource {
public:
	AutoResource(T t) : m_obj(t)
	{
		if (m_obj == NULL) {
			throw MyException("Object wasn't initialized well.");
		}
	}

	void CleanUp()
	{
		// WARNING:
		// If the assertion occurred you will have to specialize the CleanUp with the new type.
		BOOST_STATIC_ASSERT(0);
	}

	~AutoResource()
	{
		CleanUp();
		m_obj = NULL;
	}
	T get() const
	{
		return m_obj;
	}
private:
	AutoResource(const AutoResource<T>&); // No copying.
	AutoResource& operator=(const AutoResource<T>&); // No assignment.

	T m_obj;
};

template<> void AutoResource<HICON>::CleanUp()
{
	DestroyIcon(AutoResource<HICON>::m_obj);
}

template<> void AutoResource<HBITMAP>::CleanUp()
{
	DeleteObject(AutoResource<HBITMAP>::m_obj);
}

int main()
{
	AutoResource<HICON> a(LoadIcon(NULL, IDI_ERROR));
	AutoResource<HICON> b(LoadIcon(NULL, IDI_APPLICATION));
	// DrawIcon(, , , a.get());

	try {
		AutoResource<HICON> c(NULL);
	} catch(MyException&) {
		// Handle failure of initing c.
	}

	//AutoResource<int> c(2);
}
