C++: reference_wrapper

This small program:

#include <iostream>
#include <functional>
  
void add(int a, int b, int& r)
{
    r = a + b;
}
 
int main()
{
    int result = 0;
     
    using namespace std::placeholders;
    auto f = std::bind(add, _1, 20, result);
     
    f(80);
     
    std::cout << result << std::endl;
    return 0;
}

Supposedly adds 80 to 20 and prints the result; it compiles perfectly but when it gets executed it; it prints out…. 0!

Why?

Because the std::bind method parameters are passed using value semantics and, thus, the “result” variable is copied before being passed to the bound function add. Why?

Because since std::bind does not know if the parameters will still be valid when the actual invocation is performed (programmers could pass a std::function object to another function passing local variables as arguments and invoking it from there).

The solution? Pretty simple:

int main()
{
    int result = 0;
     
    auto f = std::bind(add, _1, 20, std::ref(result));
     
    f(80);
     
    std::cout << result << std::endl;
    return 0;
}

The function std::ref was used, which sends the parameter as a reference to the bound function.

What does this function std::ref do?

It is a template function that returns a std::reference_wrapper object. A std::reference_wrapper is a class template that wraps a reference in a concrete object.

It can also be done in this way:

int main()
{
    int result = 0;
     
    std::reference_wrapper<int> result_ref(result);
    auto f = std::bind(add, _1, 20, result_ref);
     
    f(80);
     
    std:.cout << result << std::endl;
    return 0;
}

and everything would continue working as expected.

As it can be seen, programmers can pass a std::reference_wrapper by value, and everything will work properly because its copy constructor copies the reference (actually, the std::reference_wrapper implementations do not store a reference but a pointer to the data being referenced, but their methods expose it as an actual reference).

Other nice use of this would be in cases where programmers need to have a container of references (the actual objects are stored in other container or elsewhere, and programmers do not need or want to have copies or pointers to them). For example, having these classes:

class A { };
class B : public A { };

If programmers want to have local variables pointing to these objects and store such variables in a container:

int main()
{
  A a, c;
  B b, d;

  std::vector<A> v = { a, b, c, d };
}

Good? No! Bad at all! The programmers here are storing instances of class A in the vector. All instances of B will be copied as instances of A (losing their specific attributes, methods, and all the polymorphic behavior they could have, and so on).

One solution? Storing pointers:

int main()
{
  A a, c; 
  B b, d;
 
  std::vector<A*> v = { &a, &b, &c, &d };
}

It works, but it is not clear whether the container consumers will be responsible for freeing the objects.

Other solution? Using references:

int main()
{
  A a, c;
  B b, d;

  std::vector<A&> v = { a, b, c, d };
}

Looks nice, but it does not compile; because programmers cannot specify reference types in a vector.

Real solution: Using std::reference_wrapper:

int main()
{
  A a, c; 
  B b, d;
 
  std::vector<std::reference_wrapper<A>> v = { a, b, c, d };
}

Someone could argue: In what scenario is this thing useful?

If some developers are creating a UI frame using Java Swing, they probably create a subclass of the JFrame class, specify their visual components as member variables, and also add them to the JFrame‘s component list. Implementing something similar in C++ using std::reference_wrapper instances would be quite elegant.

C++: std::function and std::bind

std::function and std::bind were originally part of the Boost C++ Library, but they were incorporated into the C++11 standard.

std::function is a standard library template class that provides a very convenient wrapper for a simple function, a functor, a method, or a lambda expression.

For example, if programmers want to store several functions, methods, functors, or lambda expressions in a vector, they could write something like this:

#include <functional>
#include <iostream>
#include <string>
#include <vector>
 
void execute(const std::vector<std::function<void ()>>& fs)
{
    for (auto& f : fs)
        f();
}
 
void plain_old_func()
{
    std::cout << "I'm an old plain function" << std::endl;
}
 
class functor final
{
public:
    void operator()() const
    {
        std::cout << "I'm a functor" << std::endl;
    }
};
 
int main()
{
    std::vector<std::function<void ()>> x;
    x.push_back(plain_old_func);
     
    functor functor_instance;
    x.push_back(functor_instance);
    x.push_back([] ()
    {
        std::cout << "HI, I'm a lambda expression" << std::endl;
    });
     
    execute(x);
}

As it can be seen, in this declaration:

std::vector<std::function<void ()>> x;

a vector of functions is being declared. The void () part means that the functions stored there do not receive any arguments and do not return anything (i.e., they have void as the return type). If programmers wanted to define a function that receives two integers and returns an integer, they could declare std::function as:

int my_func(int a, int b) { return a + b; }
 
function<int (int, int)> f = my_func;

The standard library also includes a function called std::bind. std::bind is a template function that returns a std::function object which, as the name suggests, binds a set of arguments to a function.

In the first code example, the functions stored in the vector do not receive any arguments, but programmers might want to store a function that accepts arguments in the same vector. They can do this using std::bind.

Having this function:

void show_text(const std::string& t)
{
    std::cout << "TEXT: " << t << std::endl;
}

How can it be added to the vector of functions in the first code listing (if even possible, because they have different signatures)? It can be added like this in the main() function:

std::function<void ()> f = std::bind(show_text, "Bound function");
x.push_back(f);

The code above shows that std::bind takes a pointer to a function (it can also be a lambda expression or a functor) and a list of parameters to pass to that function. As a result, std::bind returns a new function object with a different signature because all the parameters for the function have already been specified.

For example, this code:

#include <functional>
#include <iostream>
  
int multiply(int a, int b)
{
    return a * b;
}
 
int main()
{
    using namespace std::placeholders;

    auto f = std::bind(multiply, 5, _1);
    for (int i = 0; i < 10; i++)
    {
        std::cout << "5 * " << i << " = " << f(i) << std::endl;
    }

    return 0;
}

demonstrates another usage of std::bind. The first parameter is a pointer to the multiply function. The second parameter is the value passed as the first argument to multiply. The third parameter is called a “placeholder.” A placeholder specifies which parameter in the bound function will be filled by a runtime argument. Inside the for loop, f is called with only one parameter, and the second argument is provided dynamically.

Thanks to placeholders, even the order of arguments can be modified. For example:

#include <functional>
#include <string>
#include <iostream>
  
void show(const std::string& a, const std::string& b, const std::string& c)
{
    std::cout << a << "; " << b << "; " << c << std::endl;
}
 
int main()
{
    using namespace std::placeholders;

    auto x = std::bind(show, _1, _2, _3);
    auto y = std::bind(show, _3, _1, _2);
    auto z = std::bind(show, "hello", _2, _1);
     
    x("one", "two", "three");
    y("one", "two", "three");
    z("one", "two");
     
    return 0;
}

The output is:

one; two; three
three; one; two
hello; two; one

std::bind can also be used to wrap a method of a given object (i.e., an already instantiated one) into a function. For example, if programmers want to wrap the say_something method from the following struct:

struct Messenger
{
    void say_something(const std::string& msg) const
    {
        std::cout << "Message: " << msg << std::endl;
    }
};

into a std::function declared as follows:

using my_function = std::function<void (const std::string&)>;

The call to std::bind would look like this:

Messenger my_messenger; /* an actual instance of the class */

my_function 
    a_simple_function = std::bind(
        &Messenger::say_something /* pointer to the method */,
        &my_messenger, /* pointer to the object */,
        std::placeholders::_1 /* placeholder for the first argument in the method, as usual */
);

a_simple_function("Hello"); // will invoke the method Messenger::say_something on the object my_messenger

C++: Lambda expressions

Having this Person class:

class Person
{
  private:
    std::string firstName;
    std::string lastName;
    int id;

  public:
    Person(const std::string& fn, const std::string& ln, int i)
    : firstName{fn}
    , lastName{ln}
    , id{i}
    {
    }

    const std::string& getFirstName() const { return firstName; }
    const std::string& getLastName() const { return lastName; }
    int getID() const { return id; }
};

The programmers need to store several instances of this class in a vector:

std::vector<Person> people;
people.push_back(Person{"Davor", "Loayza", 62341});
people.push_back(Person{"Eva", "Lopez", 12345});
people.push_back(Person{"Julio", "Sanchez", 54321});
people.push_back(Person{"Adan", "Ramones", 70000});

If they want to sort this vector by person ID, a PersonComparator must be implemented to be used in the std::sort algorithm from the standard library:

class PersonComparator
{
  public:
     bool operator()(const Person& p1, const Person& p2) const
     {
        return p1.getID() < p2.getID();
     }
};

PersonComparator pc;
std::sort(people.begin(), people.end(), pc);

Before C++11, the programmers needed to create a separate class (or alternatively a function) to use the sort algorithm (actually to use any standard library algorithm).

C++11 introduced “lambda expressions”, which are a nice way to implement that functionality to be passed to the algorithm exactly when it is going to be used. So, instead of defining the PersonComparator as shown above, the same functionality could be achieved by implementing it in this way:

std::sort(people.begin(), people.end(), [](const Person& p1, const Person& p2)
{
  return p1.getID() < p2.getID();
});

Quite simple and easier to read. The “[]” square brackets are used to mark the external variables that will be used in the lambda context. “[]” means: “I do not want my lambda function to capture anything”; “[=]” means: “everything passed by value” (thanks Jeff for your clarification on this!!); “[&]” means: “everything passed by reference”.

Given the vector declared above, what if the programmers want to show all instances inside it? They could do this before C++11:

std::ostream& operator<<(std::ostream& os, const Person& p)
{
    os << "(" << p.getID() << ") " << p.getLastName() << "; " << p.getFirstName();
    return os;
}

class show_all
{
public:
    void operator()(const Person& p) const
    { 
        std::cout << p << std::endl;
    }
};

show_all sa;
std::for_each(people.begin(), people.end(), sa);

And with lambdas the example could be implemented in this way:

std::for_each(people.begin(), people.end(), [](const Person& p)
{
    std::cout << p << std::endl;
});