tags:

views:

227

answers:

5
A: 

I am not sure if I understand this correctly, but what is stopping you from having a build step which enumerates all the derived classes, estimates their sizes whatever way you use now to calculate the size of your things, and find the biggest one?

DrJokepu
If you could see the attached picture, that's exactly what we're currently doing. The problem is that in the future if another derived class is added, the logic has to be reopened and adjusted.
Dave
+3  A: 

Updated: ok ... the embedded system requirement changes things somewhat.

You could use a class to register the derived classes automatically, and then added a static instance of this class to each derived class. You still have to remember to do this though, but at least it is self contained in a single place.

Something like:

template<class T>
class RegisterPoolClass
{
public:
    RegisterPoolClass() { init_pool.Register(sizeof(T)); }
};

class Thing_1 : public Abstract_Thing
{
   static RegisterPoolClass<Thing_1> sInitializer;
    ...
};

RegisterPoolClass<Thing_1> Thing_1::sInitializer;

You could use a macro to encapsulate the code needed in each derived class in that same way ATL does.

Rob Walker
Like I mentioned in the first post, I'm having problems displaying the accompanying image. If anyone can give some help there, it might clear up questions.I'll edit the OP to give some additional insight. Thanks.
Dave
A: 

grep for classes, build a app that tests all sizes and fails if they messed up.

echo '#include"head"' > out.cpp
grep "class \w+ : TheClass" *.cpp | sed  "s/.*class \(\w\)+ : TheClass.*/assert(sizeof($1) <= MAX_SIZE); >> out.cpp
echo '#include"tail"' >> out.cpp
gcc out.cpp
./a.out
BCS
A: 

How about this:

AbstractThing.h
#ifndef ABSTRACT_THING
#define ABSTRACT_THING
class AbstractThing
{
private:
    static  size_t                  maxChildSize;
    static  bool                    maxChildLock;
    static  std::vector<type_info>  validChildren;

    static size_t   getMaxChildSize()
    {
        maxChildLock    = true;
        return maxChildSize;
    }
public:
    template<typename T>
    static  void setChildSize()
    {
        // This is to stop registering things after getMaxChildSize()
        // has been called. This check is only needed during testing
        if (maxChildLocked)
        {
            exit(1);
        }
        maxChildSize    = std::max(maxChildSize,sizeof(T));
        validChildren.push_back(typeid T);
    }
    template<typename T>
    static bool testValidType()
    {
        // While testing call this method.
        // Don't call in production to speed things up.

        // Only registered children will be allowed to get memory.
        // Or maybe generate a warning in the log if it fails.
        return validChildren.find(typeid T) != validChildren.end();
    }
};
template<typename T>
class RegisterAbsoluteThing
{
public:
    RegisterAbsoluteThing()
    {
        AbstractThing::setChildSize<T>();
    }
};
#endif
Thing1.h
#ifndef THING_1
#define THING_1

#include "AbstractThing.h"
class Thing1: public AbstractThing
{
};

namespace
{
    // Because this is in an anonymous namespace
    // It does not matter how many times different files it is included
    // This will then all be registered at startup before main.
    RegisterAbsoluteThing<Thing1>   RegisterAsValidThing1;

    // All class that derive from AbstractThing should have this block.
    // Any that do not that try and use the pool will cause the tests to fail.
}
#endif
Martin York
A: 

Could you use CTAGS or a similar parser to extract the names of all derived classes and use that to auto-generate your init_pool implementation?

Mr Fooz