Newer
Older
Import / research / other / sandbox / ObjTest / ObjTest.cpp
#include <stdlib.h>
#include <stdio.h>


struct VTable
{
	// metadata
	// function table
};

struct PImpl
{
	// member variables
	// properties, getters, setters
};

class SafeObject
{
public:
	SafeObject() {}
private:
	void *operator new(size_t size) { return (void*)-1; } // prevent heap allocation
	SafeObject(const SafeObject& other){}  // prevent copy
	SafeObject& operator =(SafeObject& val) { exit(-2); } // prevent copy
	//void* operator *() {}	       // prevent de-reference
	//void* operator ->() {}	       // prevent de-reference
	//SpecificObject& operator *() const { exit(-2); }      // prevent de-reference
	//const SafeObject& operator *() const { exit(-2); }      // prevent de-reference
	//SpecificObject* operator ->() const { exit(-3); return 0; }      // prevent de-reference

	//const SafeObject* operator ->() const { exit(-3); return 0; }      // prevent de-reference
};

class GeneralObject : public SafeObject
{
protected:
	GeneralObject()
	{
		printf("general::general\n");
	}
	void Deinit()
	{
		delete m_pImpl;
	}
	VTable*	m_vTable;
	PImpl*	m_pImpl;
};


template <typename R, typename O, typename A>
class Function
{
public:
	Function() : m_callPtr(StaticCall) {}
	static R StaticCall(Function* _this, O* obj, A args) { printf("functor uninitialized\n"); }
	inline R operator () (O* obj, A args) { return m_callPtr(this, obj, args); }
	inline Function& operator =(R (*a_call)(Function* _this, O* obj, A args)) { m_callPtr = a_call; }
private:
	R (*m_callPtr)(Function* _this, O* obj, A args);
	//R DoCall(O* obj, A args) { return m_callPtr(this, obj, args); }
};


template <typename T, typename O>
class Property
{
public:
	Property() : value(), Get(StaticGet), Set(StaticSet) {}

	static T StaticGet(Property* _this, O* obj) { return _this->value; }
	static void StaticSet(Property* _this, O* obj, T val) { _this->value = val; }

	T value;
	T (*Get)(Property* _this, O* obj);
	void (*Set)(Property* _this, O* obj, T x);

	void DoSet(O* obj, T val) { Set(this, obj, val); }
	T DoGet(O* obj) { return Get(this, obj); }
};


template <typename T>
class Property_Default
{
public:
	//Property_Default() : value() {}
	inline T Get() { return backingStoreValue; }
	inline void Set(T x) { backingStoreValue = x; }
	inline T& operator =(T& val) { return (backingStoreValue = val); }
private:
	T backingStoreValue;
};


class Class
{
public:
	Class() {}
};


class SpecificObject : public GeneralObject
{
//public:
private:
	struct Members : public PImpl
	{
		Property_Default<int> 	plainIntVal;

		Property<int,SpecificObject> x;
		Property<int,SpecificObject> y;
		//Property<Class&,SpecificObject> z;

		Function<bool,SpecificObject,int> ExampleFunctor;
	};

/*	
	struct SpecificObjectVTable // : public VTable
	{
		void (*funcA)(SpecificObject* _this, int x, int y);

	};

	static SpecificObjectVTable Functions;
	
	void FuncA(int x, int y)
	{
		((SpecificObjectVTable*)m_vTable)->funcA(this, x, y);
	}
*/

	static void XSetterTest(Property<int,SpecificObject>* p, SpecificObject* o, int val)
	{
		p->value = val + 1;
	}
	
	
	void Init()
	{
		//m_vTable = (VTable*)&SpecificObject::Functions;
		m_pImpl = new SpecificObject::Members;
		// I guess m_pImpl is now movable or that should be an aim?
		// Also aiming for not having a heap fullstop. Only reason I am allocating
		// this dynamically is because I don't want a few things:
		// 	- binary incompatibility if implementation changes and new members added
		//	- all objects having a fixed size and layout (other than the contents of
		//	what m_pImpl points to). Not really planning on never having essentially
		//	a vtable by using functors, but never a real c++ vtable (no virtual use,
		//	all the functors will be essentially as powerful as virtual though, eg
		//	can subclass and then make polymorphic calls using a reference to the
		//	base class).
	}

	static bool TestCall(Function<bool,SpecificObject,int>* f, SpecificObject* obj, int arg)
	{
		printf("real functor called\n");
	}


//	template<class R, class A>
	operator()(A)

	bool ExampleFunctor(int val)
	{
		return (*this)->ExampleFunctor(this, val);
	}

/*
	template<typename T>
	auto operator() (T func, ...)
	{
		return (*this)->func(this, ...);
	}
*/

public:
	SpecificObject()
	{
		printf("specific::specific\n");
		Init();
		(*this)->ExampleFunctor(this, 1);
		(*this)->ExampleFunctor = TestCall;
		(*this)->ExampleFunctor(this, 1);
		ExampleFunctor(1);
(this, 1);
	}

	void FuncAImp(int x, int y)
	{
		printf("x=%i,y=%i\n", x, y);
		((SpecificObject::Members*)m_pImpl)->x.Set = XSetterTest;
		((SpecificObject::Members*)m_pImpl)->x.DoSet(this, x);
		x = ((SpecificObject::Members*)m_pImpl)->x.DoGet(this);
		printf("x=%i,y=%i\n", x, y);
	}

	~SpecificObject()
	{
		Deinit();
	}

	Members* operator ->() { return (Members*)m_pImpl; }
	//SpecificObjectVTable* operator ->(int) { return (SpecificObjectVTable*)m_vTable; }
};


/*
void funcACaller(SpecificObject* _this, int x, int y)
{
	_this->FuncAImp(x, y);

}


SpecificObject::SpecificObjectVTable SpecificObject::Functions = {
	funcACaller
};
*/



//void FunctionWithArg(SpecificObject arg1, SpecificObject& arg2)
void FunctionWithArg(const SpecificObject& arg1, SpecificObject& arg2)
{
}


/*
void* malloc(size_t size)
{
	printf("BAD\n");
	exit(-1);
}
void* realloc(void* old, size_t size)
{
	printf("BAD\n");
	exit(-1);
}
void* operator new(size_t size)
{
	printf("BAD\n");
	exit(-1);
}
*/
#define new		make error if you try to compile this
#define malloc		make error if you try to compile this
#define realloc		make error if you try to compile this
//
//SpecificObject& operator *(void* obj) { exit(-2); }      // prevent de-reference


int main(void)
{
	SpecificObject testObject1;
	SpecificObject testObject2;
	//SpecificObject *testObject3 = ::new SpecificObject;
	//SpecificObject *testObject4 = new SpecificObject;
	SpecificObject *testObject5 = 0;
	testObject5 = &testObject1;
	//testObject2 = testObject2;

	FunctionWithArg(testObject1, testObject2);

	testObject1->x.DoSet(&testObject1, 10);

	//testObject1.FuncA(10, 20);

	testObject1->ExampleFunctor(&testObject1, 1);

	//testObject1.m_vTable;
	//testObject1.m_pImpl;
	printf("Line1\n");
	//testObject5->Init();
	printf("Line2\n");
	//(*testObject5).Init();
}