#include <iostream>
using namespace std;

struct TObject
{
	virtual ~TObject() = default;
};

struct TDerived : TObject
{
	~TDerived() { cout << "TDerived destroyed" << endl; }
};

void FreeAndNil(const TObject* const &Obj)
{
	cout << "FreeAndNil: Obj=" << Obj << " &Obj=" << &Obj << endl;
	const TObject *temp = Obj;
	((TObject*&)(*(void**)&Obj)) = nullptr;
	//reinterpret_cast<TObject*&>(const_cast<void*&>(*reinterpret_cast<const void * const *>(&ref))) = nullptr;
	//const_cast<TObject*&>(const_cast<const TObject * const &>(ref)) = nullptr;
	delete temp;
}

void test(const TObject* Obj)
{
	cout << "test: Obj=" << Obj << endl;
}

int main()
{
	const TObject *o1 = new TDerived;
	cout << "main: o1=" << o1 << " &o1=" << &o1 << endl;
	FreeAndNil(o1);
	cout << "main: o1=" << o1 << " &o1=" << &o1 << endl;
	test(o1);

	cout << endl;
	
	TObject *o2 = new TDerived;
	cout << "main: o2=" << o2 << " &o2=" << &o2 << endl;
	FreeAndNil(o2);
	cout << "main: o2=" << o2 << " &o2=" << &o2 << endl;
	test(o2);

	cout << endl;

	TDerived *o3 = new TDerived;
	cout << "main: o3=" << o3 << " &o3=" << &o3 << endl;
	FreeAndNil(o3);
	cout << "main: o3=" << o3 << " &o3=" << &o3 << endl;
	test(o3);

	cout << endl;

	const TDerived *o4 = new TDerived;
	cout << "main: o4=" << o4 << " &o4=" << &o4 << endl;
	FreeAndNil(o4);
	cout << "main: o4=" << o4 << " &o4=" << &o4 << endl;
	test(o4);

	cout << endl;
	
	FreeAndNil(nullptr);

	return 0;
}