C++11: polymorphic function objects

C++ supports various styles of programming and functional is one of them, however functions are not first class concept in C++ and static typing makes it almost impossible to mix or interchange callable entities of different types to be bound to same variable or to form a list of such entities based on calling semantics.

Being creative and industrious, we C++ programmers have used/abused various features of language to accomplish this, with either doing away with types completely or (mis)using inheritance and virtual functions to accomplish callbacks or delegates.

Lambdas were supposed to solve some of these problems by making it easier to define functions in-place and provide for capturing the environment, managing lifetime of captured variables defining environment is still onto the programmer though, but they are kind of typeless. Thus the variables to capture lamdas have auto type deduction. All lambdas have is calling semantics and thus the need for polymorphic function objects that don’t care about types, but just the calling semantics. There by being the “one type to rule them all” callable entity.

Technically polymorphic function objects, just function objects henceforth, use type-erasure technic. But unlike any they are selective, in sense they do enforce calling semantics. Lets consider the following code to see what this is all about, well the beauty of function objects is that you don’t need to know how they work – just that they work and are very easy to use.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <functional>
#include <iostream>
#include <cassert>

static void PrintFunction()
{
    std::cout << "PrintFunction" << std::endl;
}

struct PrintFunctor
{
    void operator()() const
    {
        std::cout << "PrintFunctor::operator()()"<< std::endl;
    }
};

int main()
{

     auto lambda1 = []()->void
                    {
                        std::cout << "lambda.. " << std::endl;
                    };

    std::function<void()> func1;

    //  since this is supposed to simulate a function
    //  you can check if this has been assigned to a
    //  callable entity or not by checking it as a boolean
    //  expression or comparing it with nullptr
    //
    assert(!func1)
    assert(func1 == nullptr);

    func1 = lambda1;
    func1();

    func1 = PrintFunction;
    func1();

    PrintFunctor printer;
    func1 = printer;
    func1();

    typedef void(*SimpleFunction_t)();
    SimpleFunction_t functionPtr = PrintFunction;

    func1 = functionPtr;
    func1();

    return 0;
}

The function objects are defined in functional header, line 1. Since they enforce calling semantics you need to specialize the template with the signature of the call, in this case void(), line 26. As this it simulates function, you must ensure that function object has been initialized with a callable entity before calling, else it will throw an exception of type bad_function_call. Lines 36, 39, 43 and 49 highlight the selective type-erasure entities with different types have been assigned to func1, but they all are callable with the same signature (try assigning variable of type int or double, in case you want to check the selective type-erasure).

I think this covers pretty much everything required to start using function object. I will do a separate post later on, about how they are implemented.