pi314159
pi314159

Reputation: 177

Understanding c++ template example

Suppose I have a class SecondTimer that counts seconds and notifies listener, assuming that listener has a special method onTimer() that accept event from timer:

template <class TName>
class SecondTimer
{
public:
    SecondTimer() : listener(nullptr), stime(0), time(1000), isStarted(false) {}

    void init(TName * _listener, int _stime)
    {
        GASSERT(_listener && "The listener can not be NULL");
        listener = _listener;
        stime = _stime;
        time = 1000;
        isStarted = false;
        listener->onTimer(stime);
    }
    inline void start() { isStarted = true; }
    inline void stop() { isStarted = false; }
    void Process(int dtime)
    {
        if (!isStarted)
            return;

        time -= dtime;
        if (time <= 0)
        {
            int ds = 1 - time / 1000;
            time = time % 1000 + 1000;
            stime -= ds;
            listener->onTimer(stime);
            //
            if (stime <= 0)
            {
                isStarted = false;
            }
        }
    }

private:
    TName * listener;
    int stime, time;
    bool isStarted;
};

I want to use it as template for 1000 different classes that implements the onTimer(int) member function.

What really happens when program will be built? Will the compiler duplicate the Init() and Process() functions for all 1000 different classes?

Upvotes: 1

Views: 509

Answers (2)

rodrigo
rodrigo

Reputation: 98526

Yes. The compiler will instantiate the whole class once for every class you use it with.

That is what is sometimes called template bloat. There are techniques to partially avoid it, and modern compilers sometimes do some clever tricks. But at the end of the day there will be a lot of duplicated code.

There are some compilers out there (I don't remember which ones that, if they happen to compile two identical functions, byte to byte, they will merge them into only one. This is technically illegal in C++, because the pointers to these functions will compare equal when they should not. But then many functions from template classes will be merged. Unfortunately, in your example only the constructor, start() and stop() will qualify, as the other ones use the template class so most likely they will generate different code.

And for this kind of problems you have to consider if it is worth it to use templates or to write a base class with a virtual function (an interface). There is a tradeoff between solving the conceptually virtual call to onTimer during runtime (slower & smaller) or during compile time (faster & bigger).

For example:

struct TName
{
    virtual void onTimer() =0;
};

class SecondTimer //no template bloat!
{
   /*...*/
};

PS: I was going to add some information here about which compilers do the merge, but then I found this answer that explains it perfectly fine.

Upvotes: 3

4pie0
4pie0

Reputation: 29754

Will compiler duplicate Init() and Process() functions for all 1000 different classes?

Yes. This is exactly what will happen. The compiler will instantiate the whole code for a class just as if you had written all of this manually. Some optimization are however possible.

Upvotes: 1

Related Questions