callable entity

C++ is language of functions – global, instance or class functions. However it is not just functions that are callable. C++ provides an operator() to make even objects behave as if they were functions, affectionately known as functors, function objects to be more precise. With C++11 lambda’s have been added to callable entity’s list.

Overall here is the summary of the callable objects:

 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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <algorithm>
//
//
template
int length(T (&arr)[N] )
{
    return N;
}
//
//
template
T* end(T (&arr)[N])
{
    return arr+N;
}
//
//
template
struct Comparator
{
    const Type& _comparisonObject;
    Comparator(const Type& obj) : _comparisonObject(obj)
    {}
    bool operator()(const Type& other) const
    {
        return other == _comparisonObject;
    }
};
//
//
int tobefound = 0;
//
//
bool find_function(int val)
{
    return tobefound == val;
}
//
//
int main()
{
    //
    int arr[] = {0,1,2,3,4,5,6,7,8,9};
    //  using function
    //  tobefound is global variable
    //
    //  Readability/Maintainability -- (Ok)
    //
    tobefound = 5;
    auto iterator1 = std::find_if(arr, arr + length(arr), find_function);
    //
    bool found1 = iterator1 != end(arr);
    //
    //
    //  using function_pointer
    //  uses the find_function's pointer to
    //  find the object, one can change the function used on fly
    //
    //  Readability/Maintainability -- (Ok--)
    //  function pointer can get ugly very quickly
    //
    typedef bool(*CompareFunc_t)(int);
    CompareFunc_t compareFunc1 = find_function;
    //
    auto iterator2 = std::find_if(arr, arr + length(arr), find_function);
    //
    bool found2 = iterator2 != end(arr);
    //
    //
    //  using functor (function object)
    //  comparator object stores state of what needs to be found
    //
    //  Readability/Maintainability -- (Good)
    //  can change the object that compares, plus no global state to be
    //  maintained
    //
    Comparator comparator(tobefound);
    //
    auto iterator3 = std::find_if(arr, arr + length(arr), comparator);
    bool found3 = iterator3 != end(arr);
    //
    //
    //  using lambda's
    //
    //  benefits of functor - functor class definition
    //
    //  Readability/Maintainability -- (Better)
    //
    auto iterator4 = std::find_if(arr, arr + length(arr),
                                [](int val) {return val == tobefound;});
    //
    bool found4 = iterator4 != end(arr);
    //
    //
    return 0;
}
//

The last bit of code demos the newly added functionality in C++11, lambda. Lambda’s are un-named function objects that can maintain state (optional). They promote use of functional programming and the use of small un-named functions that we generally need with STL. Lets look at this lambda:

1
[](int val) {return val == tobefound;}

[] – indicates start of a lambda, un-named local function object (int val) - takes one parameter of type int by value {return val == tobefound;} - defines function body. Here the variable tobefound is captured by value, for this un-named function object and it returns bool.

Here is what compiler generates for lambda’s:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    int tobefound = 5;
    auto lambda1 = [tobefound](int val) {return val == tobefound;};
    //
    //
    class UnNamedLocalFunction
    {
        int localVar;
        //
    public:
        UnNamedLocalFunction(int var) : localVar(var)
        {}
        //
        bool operator()(int val)
        {
            return val == localVar;
        }
    };
    //
    //
    UnNamedLocalFunction lambda2(tobefound);
    //
    bool is5_one = lambda1(5);
    bool is5_two = lambda2(5);

Here both lambda1 and lambda2 are equivalent. Thus lambda’s are syntactic sugar. Note this is one of the vary basic usage of lambda. This post is one of the basic post for upcoming ones on functional programming and lambdas.

See Lambda Function Post for further details

 
C++