C++: Inheritance on template specialization

When you implement something like:

/* 1 */ template <typename T> class MyClass { ... }; //template class for every T

/* 2 */ template <> class MyClass<char> { ... };  //template class full specialization for T=char

You are saying the C++ compiler: “Please, use the first template for all the MyClass<T> instances with any T except for the MyClass<T> instances where T = char”.

The problem I see with this approach is that you must provide full implementations for the template and for the <char> specialization (full implementation means: constructors, destructor, methods and attribute declarations).

In the practice, you will meet a lot of problems where you need to do a specialization of a few methods, so, the obvious solution is: inheritance.

Look at the following code snippets:

I have an “abstract” template class called ABase<T>:

template <typename T> class ABase
{
    protected:
        ABase()
        {
            printf("ABase<T> Constructor called\n");
        }

    public:
        virtual ~ABase()
        {
            printf("ABase<T> Destructor called\n");
        }

        void SetA(const T& aA)
        {
            mA = aA;
        }

    protected:
        T mA;
};

As you can see, this class does not provide a GetA() method. I want to provide two implementations for GetA(): The default implementation, and an implementation for the <char> specialization; thus, I implement: A<T> and A<char>:

template <typename T> class A : public ABase<T>
{
    public:
        A() : ABase<T>()
        {
            printf("A<T> constructor called\n");
        }

        virtual ~A()
        {
            printf("A<T> destructor called\n");
        }

        inline const T& GetA() const
        {
            printf("A<T>::GetA() called\n");
            return ABase::mA;
        }
};

//A specialization for T = char
template <> class A<char> : public ABase<char>
{
    public:
    A() : ABase<char>()
    {
        printf("A<char> constructor called\n");
    }

    virtual ~A()
    {
        printf("A<char> destructor called\n");
    }

    inline const char& GetA() const
    {
        printf("A<char>::GetA() called\n");
        return ABase::mA;
    }
};

in my quite unuseful example, you can see that two different implementations will be called when creating instances of A<T>:

A<int> objInt;
A<char> objChar;

objInt.GetA(); will call A<T>::GetA() implementation and
objChar.GetA(); will call A<char>::GetA() specialization.

I can see this like “static polymorphism” or something like “compile time polymorphism”.

The idea of inherit and provide several different methods can be useful for some kind of stuff like:

template <typename T> class StringBase { ... };

and

template <> class String<char> : public StringBase<char> { ... }; //providing a method const char* c_str() const;

template <> class String<wchar_t> : public StringBase<wchar_t> { ... }; //providing something like const wchar_t* w_str() const;

Continuing with my example, the more fascinating thing about this is when you inherit from A:

template <typename T>
class B : public A<T>
{
  ...
};

when you create an instance of B<T>: B<int> bInt; bInt.GetA(); will call the A<T>::GetA(); method; but if you instance B<char> bChar; bChar.GetA(); will call the A<char>::GetA(); specialization.

Quite powerful!!!

Advertisements

4 thoughts on “C++: Inheritance on template specialization

  1. inline const char& GetA() const
    {
    printf(“A::GetA() called\n”);
    return ABase::mA;
    }

    How do you place that in a source file? I’ve search alot and can’t figure out how. I reckon now that it is specialize, it is now possible to place it in a soruce file without shinanigans.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s