Sunday, March 07, 2004

C++ Generics

Generics in C++ are actually implemented with templates. There is some difference in the way it is implemented in C++ vs Java vs C#. I'm not very sure of the differences, but it involves the amount of work done at runtime. In C++ everything is done at compile time whereas in Java and C# it's done both at compile as well as runtime.

Anyway, templates provide a way to paramatize types. Templates allow us to NOT specify the type and program generically. This is most useful in collections like vector, deque, map etc.. since you don't need to create a class for every kind of type that could be held in the collection. C++ does not have a unified type system like Java and C#, so if you did NOT have templates, you would have the tedious job of creating something like an intVector that will hold only integers, stringVector for only strings etc...

With templates, you can keep the type unspecified. When you actually want to use the class with an integer, you just specify the type to be int. Before compiling, the compiler will go through the code, find the unspecified type in the class and replace it with the one you specified. This is, I guess, pre-processing... similar to macro's. But the difference is that it is type safe since after replacing with the specific type, the compiler will check to see if it supports the operation (like +... integral types support this operation, but bool doesnt). If it doesn't suport the op, the compiler will generate (sometimes amazingly cryptic) error messages.

I guess a simple ex may help...

template <typename T>
class myVector
{
    private:
        T* m_elements;

    public:

        myVector( size_t n )
        {
            this->m_elements = new T[ n ];
        }

        ~myVector()
        {
            delete[] this->m_elements;
        }

        void set( size_t i, T v )
        {
            this->m_elements[ i ] = v;
        }

        T get( size_t i )
        {
            return this->m_elements[ i ];
        }
};


Here, T is the unspecified type. myVector is a collection that holds on to T's. When you want to retreive an element at a specific location, get returns a T. And similarly, to add values to the collection you use set.

To actually use this class you'd need to specifiy a type...

int main()
{
    myVector<int> intVector( 2 );

    intVector.set( 0, 11111 );
    intVector.set( 1, 22222 );

    int val1 = intVector.get( 0 );
    int val2 = intVector.get( 1 );
}


So here you specify the type you want myVector to store as int. When the compiler sees myVector<int>, it will create a copy of your template class, with the T's replaced with ints. It will do the same for every type you specify. So if you have myVector<string>, it will have a separate copy of the code with the T's replaced with string. So the idea is to let the compiler do the work.

So hope this gave you some idea. Dinesh/Hrishi correct any mistakes I might have made.

No comments: