Bug Vanquisher

24 May 2008

C++ – The Power of Templates

Filed under: C++ — Tanveer Badar @ 5:52 PM

Do you read Ian Griffiths? If not, please start reading. Belongs in the group of smart people (by my classification).

But smarties don’t know everything either, nor do I. However, there is one thing Ian gets wrong in one of his articles. He specifically writes,

The fact that there is no implied type becomes even more striking when you consider some more interesting Python examples. Because Python performs its type checks even later than C++, you have even more flexibility:

def speak(speaker, mood):
    if mood == "verbose":
        speaker.WaxLyrical()
    elif mood == "shy":
        speaker.Whisper()
    else:
        speaker.Talk()

yada yada yada…

Note that in C++ we’d see a different result here. Python defers its type checking until the point at which you try to use a member. In a C++ template, the check is done when the template is instantiated. So C++ would actually require all three methods to be present, despite the fact that only one will be used for any given execution of the speak method. So in C++ the constraints a template can impose on its parameter are less dynamic than in Python.

However, the part about "C++ would actually require all three methods to be present" is wrong assertion. It is entirely possible to have the same behavior like Python in C++. Never, ever, underestimate the power of compile time Turing-complete templates available. :)

The code given below requires only one function at a time. My only humble request is to compile it on a sane compiler (implicitly exclude MSVC 7 and earlier).

#ifdef _MSC_VER && _MSC_VER <= 1300

#error Can’t you read English. THIS STUFF REQUIRES MSVC 8 OR HIGHER!!!

#endif

struct A { void whisper( ) { } };

struct B { void shriek( ) { } };

struct C { void snarl( ) { } };

template< typename T > struct invoker

{

    static void invoke( T )

    {

    }

};

template< > struct invoker< A >

{

    static void invoke( A obj )

    {

        obj.whisper( );

    }

};

template< > struct invoker< B >

{

    static void invoke( B obj )

    {

        obj.shriek( );

    }

};

template< > struct invoker< C >

{

    static void invoke( C obj )

    {

        obj.snarl( );

    }

};

template< typename T > void f( T obj )

{

    invoker< T >::invoke( obj );

}

void g( )

{

    f( A( ) );

}

Hopefully, a little more C++ will bring peace and harmony in the world :). One can only hope.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

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

Create a free website or blog at WordPress.com.

%d bloggers like this: