Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Possible with templates?
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
wizof...@hotmail.com  
View profile  
 More options Nov 2 2005, 6:41 am
Newsgroups: comp.lang.c++.moderated
From: wizof...@hotmail.com
Date: 2 Nov 2005 06:41:28 -0500
Local: Wed, Nov 2 2005 6:41 am
Subject: Possible with templates?
Ok, this is really just a "is there anyone who thinks this is a
worthwhile challenge" sort of query!

Basically, I'm working on data structure design whereby all the objects
in my data structure have their properties referenced by integer ids.
Property values are also always integral.  The naive implementation
would be to store all properties in an int-to-int map, and let any
object hold any value for any property.

Unfortunately, maps are problematic for two simple reasons: size and
speed.  The application needs to work with 100s of 1000s of objects,
and each object can have up to 12 properties (although most only have 4
or 5).  It needs to be able to very very rapidly access basically every
property of every object, and not impose unreasonable memory
requirements.  The performance testing I did basically ruled out maps
on this basis.

Now much of the time the properties required are known at compile time.
 That is, I might have code like:

int color = object.property(property_color);

Basically, I need this to compile to code that isn't measurably slower
than a direct reference to a data member, e.g.:

int color = object.color;

Furthermore, in order to reduce memory requirements, I've worked out
how pack all the possible properties into either 16 or 8 bit integers,
some of them signed, some of them unsigned.

I also know that each object has a key property - "type" - that
determines which other properties make sense for an object.  So an
object of type, say, "sound" doesn't have a color, whereas an object of
type "car" would.

With this in mind I came up with a system of macros that allows me to
do the following:

template <bool get>
inline void getset(Object& obj, int prop, int& value, int type = 0)
{
        if (type == 0) type = obj.props[0];
        switch (type)
        {
        case objectSound:
                GETSETPROP3(
                        int16_t,        propPitch,
                        uint16_t,       propDuration,
                        uint16_t,       propVolume);
        case objectCar:
                GETSETPROP4(
                        uint16_t,       propColor,
                        uint8_t,        propCylinders,
                        uint8_t,        propDoors,
                        uint16_t,       propEngineSize);
//      etc.etc.;
        }

}

I've comfirmed by looking at the disassembly and some performance
testing that this does exactly what I want for cases where both the
object type and property id are known at compile time, and for cases
where one or the other or both are not (in fact, it's damn impressive
the sort of optimizations compilers can do in this regard!).  The 'both
unknown at compile time' scenario pretty much only occurs when
serializing, but even this can't afford to be as slow as a std::map
lookup.

The part I don't like about it is the GETSETPROP# macros, which need to
be defined for every number between 1 and 12, and use some slightly
ugly casting, e.g.:

#define SPROP(P, N) case P: assign<get>(p->m##N, value); return;
#define GETSETPROP4(t1, p1, t2, p2, t3, p3, t4, p4) \
{       \
 struct p_ { int16_t pad; t1 m1; t2 m2; t3 m3; t4 m4; }; \
 p_* p = reinterpret_cast<p_*>(&obj); \
 switch (prop) { SPROP(p1, 1) SPROP(p2, 2) SPROP(p3, 3) SPROP(p4,  4)

}; \
 return; \
};

I accept the casting will be necessary one way or another (or you could
cheat and use a union), but this is really just a method of packing as
much data as possible into a limited block of space.

The obvious question is how much of this can be done with just template
meta-programming?  I know you can define type chains and the like, but
I couldn't really see how it would help me here.

If I can scrap the macros entirely I would be very happy, but
everything I've tried so far has failed to get me anywhere.

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.