Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reducing template bloat with inheritance

Does anyone have experience reducing template code bloat through inheritance?

I hesitate rewriting our containers this way:

class vectorBase
{
  public:
    int size();
    void clear();
    int m_size;
    void *m_rawData;
    //....
};

template< typename T > 
class vector : public vectorBase
{
    void push_back( const T& );
    //...

};

I should keep maximum performance while reducing compile time. I'm also wondering why Standard Library implementations do not uses this approach.

like image 923
benoitj Avatar asked Jun 14 '10 13:06

benoitj


3 Answers

Only very few operations on a vector make sense if you don't know what type the stored elements are. For example the clear() method you added to your base class needs to call the destructors of the elements removed from the vector, so it needs to know their type and needs to be templated.

There is also really not much you can do with the a void *m_rawData without knowing the types of the things inside it, basically all operations on it at least have to know the size of the stored type. The only thing I can think of would be that you can free() it if you know that it contains no elements (if it contains elements you have to call their destructors). Allocating, setting and accessing elements all doesn't work if you don't know where the individual elements start and end. Also the implementation of all the methods would be much cleaner and simpler if m_rawData would be a properly typed T* instead.

A size() method in the base class would only work if its only job is to return a m_size member variable, but a vector doesn't necessarily have to store the size explicitly (the implementations I know of don't). You could probably implement is so that the size is stored explicitly, but then again size() is probably not a method that takes long to compile, even if it's templated.

All together I don't think there are a lot of methods remaining, that are implementable in a base class. Most operation on a vector need to know about the elements stored in it.

like image 87
sth Avatar answered Sep 25 '22 03:09

sth


I think this is a premature optimization. In general except in embedded systems, disk space and memory are plentiful and cheap, so there's no reason to try to optimize for a small amount of code space. By keeping it all in the template code it makes it more obvious what's going on rather than using inheritance which would complicate things.

Additionally most applications aren't going to be generating hundreds of instantiations, and for each T not all methods may be used, reducing the code footprint further.

Only if there were extremely tight memory considerations (embedded) would I consider different possible approaches (including the one you presented).

EDIT: I'm not sure that there's much gain to be had in a little of standard container cases since they still need a lot of template code. For internal classes that have only a small amount of template-specific code and lots of common logic this could definitely help both generated code and compilation speed. I suspect it isn't used often because it's more complex and the benefits are restricted to certain scenarios.

like image 30
Mark B Avatar answered Sep 24 '22 03:09

Mark B


I understand your approach.

To be frank I have used it... although obviously not for STL containers: their code is virtually bug-free and optimized and I am highly unlikely to come up with a better implementation on my own!

I don't care much about compile-time: it's an embarrassingly parallel problem (apart from link) and distcc etc take care of all the troubles you can have even with a large codebase. And I mean large, I work at a company which required a new compiler from HP because the version we had didn't not support more than 128Ko... in the command line of the linker. And it was only one of the application, and it was a few years ago, and they thankfully splitted it up in several chunks since.

However, as much as I don't care about compile-time, I do care a lot about reduced dependencies and binary compatibility. And thus when I write templated code of my own I do check if it's possible to factor some operations outside of the templated code.

The first task is to isolate those point where you can really gain. Getting one line of code out is not worth your time, you want to get full functions.

The second task is to decide whether or not you wish to keep them inlined. It depends whether or not you care about performance, the overhead of a function call may or may not be important to you.

However I would certainly not use inheritance for the job. Inheritance is a IS-A relationship: it defines an interface, not an implementation. Either use Composition or simply free functions that you stash in a utility namespace (detail like in Boost ?).

like image 27
Matthieu M. Avatar answered Sep 26 '22 03:09

Matthieu M.