Quantcast
Viewing latest article 2
Browse Latest Browse All 5

Understanding C++ 0x: Function pointers

What is a function pointer, anyway? Well, imagine that you’re just a wee lad(dy) in your grassy backyard playing a game with your brother Al, your sister Beatrice (the name’s a family tradition – she never liked it), and one of your cousins in town for the holidays. The rules of the game are as follows: each person writes down one action on a slip of paper and then sticks that slip into a hat. You then take turns drawing actions from the hat, and whatever action you draw you’re stuck doing. The game goes as follows:

  1. Al draws a slip that says “Do three cartwheels”. He does three cartwheels.
  2. Your cousin draws a slip that says “Eat mud”. Luckily for your cousin, he won a mud-eating championship in his younger years. He eats the mud.
  3. Etc…

This situation is strikingly similar to how you can use functions and function pointers in C++.

  1. Define the function (write the action down on the slip of paper). This is just like any other function definition – you just have to say what you want the function to do.
    int biscuitCount = 10;
    
    void EatBiscuits(int biscuitsEaten)
    {
       biscuitCount -= biscuitsEaten;
    }
    
  2. Store the function into a variable (put the slip of paper into the hat). Now we’re getting to the cool part – and the part where C++ 0x really starts to shine through. First, here’s how we would have stored the function pointer in the old C++:
    void (*myFunctionPointer)(int) = &EatBiscuits;
    

    Yea – it’s pretty ugly to say the least. Just about everyone in the world had to look up the function pointer syntax whenever they used one. Now let’s take a look at the new C++ 0x function pointer syntax:

    std::function<void (int)> myFunctionPointer = &EatBiscuit;
    

    In my opinion -much easier to remember. The fact that the types are inside of the template arguments seems to fit much better with the rest of C++. But now that the function is inside of a variable, what do we do with it?

  3. Calling the function (eating the mud). The really neat thing here is that at this point, we don’t care about which function is stored in the variable holding the function pointer. All we know is that we’re going to call it. The syntax for this call hasn’t changed at all – for both the old C++ and C++ 0x, it looks like this:
    myFunctionPointer(3); // Eat 3 biscuits
    

    Easy stuff!

Now, the example that I just gave of function pointers wasn’t really that useful. We could have just called the EatBiscuits function without all of that function pointer nonsense. However, it’s fairly easy to imagine how function pointers could become incredibly useful. One example is the idea of a callback function in C++, just like the ones that are frequently seen in Javascript. For example, in Windows you could do something like:

std::function<void ()> waitingCallback = NULL;

void MyCallbackFunctionOne()
{
   cout << "Wheeeeee! Finished!" << endl;
}

void MyCallbackFunctionTwo()
{
   cout << "Booooooo! I crave more programming!" << endl;
}

void StartWaiting(std::function<void ()> callback)
{
 waitingCallback = callback;

 // Starts a timer that tics once every 100 milliseconds
 SetTimer(1, 500, NULL);
}

afx_msg void OnTimer(UINT_PTR nIDEvent)
{
 // Stops the timer
 KillTimer(1);

 // Calls the callback function
 waitingCallback();
}

// Later in your code you can call...
std::function<void ()> actualCallback;

if(someCondition)
   actualCallback = &MyCallbackFunctionOne;
else
   actualCallback = &MyCallbackFunctionTwo;

StartWaiting(actualCallback);

Notice how OnTimer doesn’t care whether it’s calling MyCallbackFunctionOne or MyCallbackFunctionTwo – it just calls whatever it was passed. How cool is that? Need more uses? You could make a window that decreases its opacity until it’s completely faded out, then calls a callback at the completion of the fading. Now we’re talking.

Knowing about function pointers can introduce an entirely new way of thinking about programming. Rather than thinking of a program as a linear path, you can start to think of a program instead as various events occurring and reacting to each other, which is often much more similar to the way that complex programs actually work. Function pointers are very powerful.

Just two quick notes before we conclude. First, the declarations for anything related to the new C++ function pointers is in the header. Second, the C++ 0x goodies are usually in the namespace std::tr1 (which stands for Technical Report 1 – the paper that proposed many of the changes). Therefore, you should make sure that you have the right namespace qualification for any function pointer declaration (std::tr1::function) and that you include the functional header:

#include
...
std::tr1::function<void ()> myCallback;

Now, go forth and enjoy – happy programming!

Edit: Fixed a problem with the less than signs for the function templates not showing up correctly.


Viewing latest article 2
Browse Latest Browse All 5

Trending Articles