Chris Shearer Cooper
2010-09-28 13:54:52 UTC
I've inherited some legacy code that I'm trying to fix up, basically
what it is doing is creating a table of items and accessor functions
like this:
typedef void (CWnd::*VF)(void);
struct X
{
char name[32];
int type;
VF getFunc;
VF setFunc;
};
X table[] =
{
{ "Name", TYPE_STR, (VF)&Y::GetName, (VF)&Y::SetName },
{ "Value", TYPE_INT, (VF)&Y::GetValue, (VF)&Y::SetValue },
{ "Length", TYPE_DOUBLE, (VF)&Y::GetLength, (VF)&Y::SetLength }
};
Where of course the functions look like this:
CString Y::GetName(void);
int Y::GetValue(void);
double Y::GetLength(void);
So basically there is no type-safety going on, if someone unknowingly
changes the signature of GetValue(), the code happily compiles and
then crashes in bizarre ways.
What I'm trying to do, is think of a way to insert some type-safety
into this system with a couple of restrictions:
1) can't rewrite the entire table initialization section (change must
be able to be implemented incrementally)
2) can't add a lot of additional data members to the struct X (tables
are huge already)
3) can't call a class constructor for each line in the table (table
should be generated at compile-time, not run-time)
I tried putting a variety of function signatures into a union, but
then I can't find any way to initialize a union as part of a struct
inside an array.
What I would like is something like a macro that I can insert, one
line at a time, into the table, so I get something like this:
X table[] =
{
STR("Name", &Y::GetName, &Y::SetName ),
{ "Value", TYPE_INT, (VF)&Y::GetValue, (VF)&Y::SetValue },
{ "Length", TYPE_DOUBLE, (VF)&Y::GetLength, (VF)&Y::SetLength }
};
and somehow this STR() macro enforces the correct parameters and
return type on GetName() and SetName().
Can I somehow use a type_cast<> to first ensure the function has the
right signature, and then blast it into the generic VF for insertion
into the struct?
Thanks,
Chris
what it is doing is creating a table of items and accessor functions
like this:
typedef void (CWnd::*VF)(void);
struct X
{
char name[32];
int type;
VF getFunc;
VF setFunc;
};
X table[] =
{
{ "Name", TYPE_STR, (VF)&Y::GetName, (VF)&Y::SetName },
{ "Value", TYPE_INT, (VF)&Y::GetValue, (VF)&Y::SetValue },
{ "Length", TYPE_DOUBLE, (VF)&Y::GetLength, (VF)&Y::SetLength }
};
Where of course the functions look like this:
CString Y::GetName(void);
int Y::GetValue(void);
double Y::GetLength(void);
So basically there is no type-safety going on, if someone unknowingly
changes the signature of GetValue(), the code happily compiles and
then crashes in bizarre ways.
What I'm trying to do, is think of a way to insert some type-safety
into this system with a couple of restrictions:
1) can't rewrite the entire table initialization section (change must
be able to be implemented incrementally)
2) can't add a lot of additional data members to the struct X (tables
are huge already)
3) can't call a class constructor for each line in the table (table
should be generated at compile-time, not run-time)
I tried putting a variety of function signatures into a union, but
then I can't find any way to initialize a union as part of a struct
inside an array.
What I would like is something like a macro that I can insert, one
line at a time, into the table, so I get something like this:
X table[] =
{
STR("Name", &Y::GetName, &Y::SetName ),
{ "Value", TYPE_INT, (VF)&Y::GetValue, (VF)&Y::SetValue },
{ "Length", TYPE_DOUBLE, (VF)&Y::GetLength, (VF)&Y::SetLength }
};
and somehow this STR() macro enforces the correct parameters and
return type on GetName() and SetName().
Can I somehow use a type_cast<> to first ensure the function has the
right signature, and then blast it into the generic VF for insertion
into the struct?
Thanks,
Chris