Original Post
So, I've been playing around with C++ template magic. Being touched in the head, I got to thinking about aspect oriented programming, functors, and classes. What if one used member functors to allow each function in a class to have private state -- and more importantly, to allow metafunction programming? The simplest examples include "this function should only run once", or "this function should count the number of times it runs", or "this function should aquire a write lock on the class during it's execution". I'm not certain if the result is worthwhile. But as a concept it looks interesting to me. :) Here is a quick stab at it: The above compiles (with warnings) under MSVC++2003, and I suspect it is standards-ok C++ code. I'm not certain that it saves much typing, but I did manage to move metafunction logic out of the implementation of the function and into the declaration of the functor.
#include <stdio.h>
#include <windows.h>
template<typename parentptr, typename retval>
class MemberFunctor {
protected:
parentptr const self;
virtual retval Work() = 0;
MemberFunctor(parentptr self_):self(self_) {}
public:
retval operator()() {
return Work();
}
};
template<typename parentptr, typename retval>
class RunOnceMemberFunctor:
public MemberFunctor<parentptr, retval>
{
private:
bool has_run;
retval cached;
protected:
RunOnceMemberFunctor(parentptr self_):MemberFunctor<parentptr, retval>(self_), has_run(false), cached() {}
public:
retval operator()() {
if (!has_run) {
has_run = true;
cached = Work();
}
return cached;
}
};
class test {
int data;
public:
class Init:public RunOnceMemberFunctor<test*, bool> {
bool Work() {
#ifdef _DEBUG
OutputDebugString("Initialize called!\n");
#endif
self->data = 'init';
return true;
};
public:
Init(test* self_):RunOnceMemberFunctor<test*, bool>(self_){};
} Initialize;
class Clean:public RunOnceMemberFunctor<test*, bool> {
bool Work() {
#ifdef _DEBUG
OutputDebugString("Clean called!\n");
#endif
bool retval = self->data == 'init';
self->data = 'gone';
return retval;
}
public:
Clean(test* self_):RunOnceMemberFunctor<test*, bool>(self_){};
} CleanUp;
class Value:public MemberFunctor<test*, int> {
int call_count;
int Work() {
++call_count;
#ifdef _DEBUG
char tmp[1024] = {0};
sprintf(tmp, "Called %d times, value 0x%08x\n", call_count, self->data);
OutputDebugString(tmp);
#endif
return self->data;
};
public:
Value(test* self_):MemberFunctor<test*, int>(self_), call_count(0) {};
} Read;
class Reference:public MemberFunctor<test*, int&> {
int call_count;
int& Work() {
++call_count;
#ifdef _DEBUG
char tmp[1024] = {0};
sprintf(tmp, "Called %d times, value 0x%08x\n", call_count, self->data);
OutputDebugString(tmp);
#endif
return self->data;
};
public:
Reference(test* self_):MemberFunctor<test*, int&>(self_), call_count(0) {};
} Write;
test():Initialize(this), CleanUp(this), Read(this), Write(this), data(0) {}
};
bool tester() {
test a;
int v = a.Read();
bool b = a.Initialize();
v = a.Read();
b = a.CleanUp();
v = a.Read();
b = a.Initialize();
v = a.Read();
b = a.CleanUp();
v = a.Read();
a.Write() = 0xBAADF00D;
v = a.Read();
return true;
};
bool meh = tester();