#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();
}