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?
A:
DrJokepu
2008-11-12 00:38:52
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
2008-11-12 00:45:35
+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
2008-11-12 00:42:31
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
2008-11-12 00:48:06
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
2008-11-12 00:43:56
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
2008-11-12 00:44:52
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
2008-11-12 01:50:31