Ovanes,
That's pretty neat, I never knew you could do that. But I don't think
it gets me there. If I'm coming in with an unknown const char *, I can
get the extern equivalent via looping through a global registry doing
strcmp()s. But once I get my index into the registry I can't place it
into the template specification ( such as "TypeId
v;").
Also I was hoping to create all the required stuff via a single MACRO
per class member, for example I was hoping to create something like
this:
class Point
{
getMemberValue()
{
INDEX_MACRO(x)
INDEX_MACRO(y)
}
int x;
int y;
}
Using the templated TypeId struct I have to define a whole lot of
extern's out of the class and function declarations inside the class
for each member.
And probably the toughest problem with this, how to create a simple
way to "expand the tree" of all possible access() functions. For
example, if I'm coming in with an index of "corner:x" into Rectangle
object, I don't want to know about a Point just an int. So, I would
need a special type just for "corner:x" and a access() function that
takes this type and return a int.
In case you're interested below is what I came up with (minus the
MACROs and minus it being able to compile). Thanks for you help, I
probably have to think of a different solution.
template
struct TypeId
{};
///header
// for Point
extern const char x[] = "x";
extern const char y[] = "y";
typedef TypeId<x> x_Accessor;
typedef TypeId<y> y_Accessor;
// for Rectangle
extern const char corner[] = "corner";
extern const char width[] = "width";
extern const char height[] = "height";
typedef TypeId<corner> corner_Accessor;
typedef TypeId<width> width_Accessor;
typedef TypeId<height> height_Accessor;
extern const char corner_x[] = "corner:x";
extern const char corner_y[] = "corner:y";
typedef TypeId corner_x_Accessor;
typedef TypeId corner_y_Accessor;
extern const char *typeid_registry[] =
{
x,
y,
corner,
width,
height,
corner_x,
corner_y,
NULL
};
struct PointClass
{
// get
int access(x_Accessor)
{
return x;
}
int access(y_Accessor)
{
return y;
}
// set
void set(x_Accessor, int value)
{
x = value;
}
void set(y_Accessor, int value)
{
y = value;
}
int x;
int y;
};
struct RectangleClass
{
// get
int access(width_Accessor)
{
return width;
}
int access(height_Accessor)
{
return height;
}
PointClass access(corner_Accessor)
{
return corner;
}
int access(corner_x_Accessor)
{
return corner.x;
}
int access(corner_y_Accessor)
{
return corner.y;
}
// set
void set(width_Accessor, int value)
{
width = value;
}
void set(height_Accessor, int value)
{
height = value;
}
void set(corner_Accessor, PointClass value)
{
corner = value;
}
void set(corner_x_Accessor, int value)
{
corner.x = value;
}
void set(corner_y_Accessor, int value)
{
corner.y = value;
}
int width;
int height;
PointClass corner;
};
struct BlobClass
{
// a whole lot of access()/set() functions
RectangleClass boundingBox;
int centroid;
float mass;
};
int main(void)
{
RectangleClass rc;
rc.corner.x = 55;
rc.corner.y = 66;
rc.width = 77;
rc.height = 88;
std::string simpleSrcKey = "width";
std::string simpleDestKey = "corner:x";
for(int srci = 0; typeid_registry[srci] != NULL; ++srci)
{
if(!strcmp(typeid_registry[srci], simpleSrcKey.c_str() ))
{
for(int dsti = 0; typeid_registry[dsti] != NULL; ++dsti)
{
if(!strcmp(typeid_registry[dsti], simpleDestKey.c_str() ))
{
TypeId dst;
TypeId src;
rc.set(dst, rc.access(src));
}
}
}
}
return 0;
}
On 1/29/08, Ovanes Markarian wrote:
Yes, you can define your types based on const char* and overload template
functions on them.
//using structs to skip explicit public access specifiers
///header
extern const char SomeName[];
template
struct TypeId
{};
typedef TypeId<SomeName> MemberX_Accessor;
struct ClassWithMembers
{
void access(MemberX_Accessor)
{
...
}
template<class T>
void access(T)
{
/// issue error here, no accessor specified!!!
}
private:
MemberX x;
};
///cpp
extern const char SomeName[] ="memberX";
I hope that example brings you to some useful ideas.
Regards,
Ovanes
On Jan 29, 2008 3:34 PM, Joseph Fradley wrote:
I have a problem that I would like to solve in the most generic
non-intrusive way possible (such as boost serialization). What I want is to
access class members both via it's initially designed accessors but also via
a "const char *" key. In addition, I want to pass list of key's (via a
vector of const char * or a single delimited multikey char *) to get nested
member access.
For example:
...
// these should be equivalent
Point p;
int val;
val = p.x;
val = p.getX();
p.getMemberValue("x", val);
// there also
Rectangle r;
int val;
Point pVal;
r.getMemberValue("corner:x", val);
r.getMemberValue("corner", pVal);
I thought about having a templated function similar to the serialize()
function called 'getMemberValue()', where each 'if' block below could be
wrapped into a MACRO taking just the member name.
template< class T >
bool getMemberValue(const char *key, T & value)
{
if(!strcmp(key, "member"))
{
value = this->member;
return true;
}
return false;
}
This appears to work fine for one level deep but if I want the behavior
such as the above rectangle example, I run into trouble. I end up with a
function implementation like this for the 'Rectangle' class
template< Point >
bool getMemberValue(const char *key, Point & value)
{
if(!strcmp(key, "corner"))
{
value = this->corner; // Point
return true;
}
if(!strcmp(key, "width"))
{
value = this->width; // int
return true;
}
if(!strcmp(key, "height"))
{
value = this->height; // int
return true;
}
return false;
}
This fails because it ends up trying to set an integer value to a Point
variable.
Anybody have any suggestions?
Joe
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users