C++

C++ std_function

In C++, std means standard. C++ can have a defined class from which objects are instantiated. A normal defined function, is like a class. The function call is like an object to the defined function class. A function call, at different times, with different arguments, is like different function objects. Now, C++ has predefined function classes where different function objects can be officially instantiated. A function object can also be used, as a function call. It can be a callback function argument in another function call. A function object can take the place of a pointer to a normal function.

The std::function is a function prototype declaration with the name, function() in the header <functional>, of the <utility> library. This means, in order to use std::function, the <functional> or <utility> header has to be included into the program. The std::function is also a wrapper that takes a function object as argument, to produce another function object.

This article explains C++ std::function, beginning with some predefined function classes.

Article Content

– Some Predefined function classes

– std::transform

– std::function Proper

– Conclusion

Some Predefined function Classes

The functional header has many predefined function class prototypes, in the categories of, reference_wrapper, arithmetic operations, comparisons, class compare_three_way, logical operations, bitwise operations, bind, polymorphic function wrappers, searchers, and class template hash.

In the arithmetic category, two of the function class prototypes are:

template<class T = void> struct negate;

and

template<class T = void> struct plus;

Note: a struct is a kind of class. The first one would negate numbers in a list. The second one would add corresponding numbers of two lists together, resulting in one list of the additions.

std::transform

There is the std::transform() function in the algorithm library. This function would take the beginning and end of a vector and use the negate function object to negate all the elements of the vector. The negate function object is the last argument of the transform() function call. A prototype (syntax) is:

template<class InputIterator, class OutputIterator, class UnaryOperation>

constexpr OutputIterator transform(InputIterator first1, InputIterator last1,

OutputIterator result, UnaryOperation op);

where OutputIterator is a second vector for the resulting negated numbers. OutputIterator is also returned.

The following program shows the use of the syntax:

#include <iostream>

#include <algorithm>

#include <functional>

#include <vector>

using namespace std;

    vector vtr1 = {1, 2, 3, 4, 5};
    vectorvtrOut(5);

    int main()
    {
transform(vtr1.begin(), vtr1.end(), vtrOut.begin(), negate());

        for (int i=0; i<vtrOut.size(); i++)
cout<<vtrOut[i] << ' ';
cout<<endl;
        return 0;
    }

The output is:

-1 -2 -3 -4 -5

The directives include, iostream, algorithm, functional, and vector headers. The standard namespace is used. The input and output vectors are of the same size. The std::transform() function is used without, returning, since the return item is a transform function argument. The for-loop prints out the negated numbers at the output. A return item for the transform function would have been coded as follows:

vtrOut.begin() = transform(vtr1.begin(), vtr1.end(), vtrOut.begin(), negate<int>());

In an overloaded form, the transform() function would take the beginning and end of one vector. Then the beginning of another vector, and use the a plus function object to add the corresponding numbers of the two vectors to have a new vector with the sums. The plus function object, is the last argument of the transform function call, for this purpose. The prototype (syntax) is:

template<class InputIterator1, class InputIterator2,

class OutputIterator, class BinaryOperation>

constexpr OutputIterator transform(InputIterator1 first1, InputIterator1 last1,

InputIterator2 first2, OutputIterator result, BinaryOperation binary_op);

where OutputIterator is a third vector for the resulting sum numbers. OutputIterator is also returned, but this does not have to be implemented. See the following program:

#include <iostream>

#include <algorithm>

#include <functional>

#include <vector>

using namespace std;

    vector vtr1 = {1, 2, 3, 4, 5};
    vector vtr2 = {10, 20, 30, 40, 50};
    vectorvtrOut(5);

    int main()
    {
transform(vtr1.begin(), vtr1.end(), vtr2.begin(), vtrOut.begin(), plus());

        for (int i=0; i<vtrOut.size(); i++)
cout<<vtrOut[i] << ' ';
cout<<endl;
        return 0;
    }

The output is:

11 22 33 44 55

The directives include, iostream, algorithm, functional, and vector headers. The standard namespace is used. The two input and one output vectors, are of the same size. The std::transform() function is used without, returning, since the return item is a transform function argument. The for-loop prints out the summed numbers at the output.

std::function Proper

All the above has explained how to use a function object, professionally. It is possible for the programmer to write his own function like the transform() function and use his own function object that he has written.

std::function is not a big deal. It is a wrapper that would take any function object as argument. This section of the article illustrates how to create a simple function object, and have it wrapped in std::function.

A function object is a callable object. A callable object is any object that can be used like a function. An example of a function class, is shown in the following code:

#include <iostream>

#include <functional>

using namespace std;

struct StructFn {
        int operator() (int a, int b) {
            int c = a + b;
            return c;
        }
    };

 StructFnfn

This is the top part of the program, lacking only the C++ main function. A struct is like a class. This code has the definition of a struct, called StructFn (equivalent to class-name). The struct has just one member, which is the parentheses operator. An operator is somewhat a function. This function takes two integers as arguments, and returns another integer. It actually returns the sum of the two integers. The struct, StructFn is a function object type.

The instantiated object of the struct, StructFn is fn. “std::function” itself, is another type (class). The last statement in the above code, instantiates an object of std::function (where std:: is omitted because it is in “using namespace std;”). The name of the standard object for “std::function”, is f. “f()” is an object constructor. In this case, its only argument, is fn, which is an object of the function class, StructFn. This last statement wraps the function object.

The operator (function) of the function class (struct), has two arguments of types int and int. It returns another int. This signature features can be represented as: int(int, int). That is why, the template specialization, of the function construction, is <int (int, int)> .

The syntax for the function constructor, used above, is:

template<class R, class... ArgTypes> class function<R(ArgTypes...)>;

The remainder of the program, is the C++ main() function. It is:

int main()

{

int z = f(2, 3);

cout << z << endl;

return 0;

}

The output is 5. f(2,3) was used instead of fn(2,3).

The advantage of std::function is that, it can take any function object, once the arguments and the return type, of the function taken, are known.

The above function object can be modified, to be used as a plus function callback, in the transform function call.

Conclusion

The std::function is of the functional header, that has to be included into the program in order for it to be used. It wraps a function object. The function object has to be its argument (of the std::function construction). A function object is a callable object. A callable object is any object that can be used like a function. The advantage of std::function is that, it can take any function, once the arguments and the return type, of the function taken, are known.

About the author

Chrysanthus Forcha

Discoverer of mathematics Integration from First Principles and related series. Master’s Degree in Technical Education, specializing in Electronics and Computer Software. BSc Electronics. I also have knowledge and experience at the Master’s level in Computing and Telecommunications. Out of 20,000 writers, I was the 37th best writer at devarticles.com. I have been working in these fields for more than 10 years.