Advanced Example with Functional Objects

Lesson Introduction

Hello! In our journey through functional programming in C++, we've explored currying, partial application, and functors. Today, we'll dive into an advanced example using functional objects, or functors, in combination with the powerful Boost.Range library. The goal is to deepen your understanding of how to create and utilize functional objects to make your code more modular and reusable, especially in a real-world context like adjusting employee salaries.

By the end of this lesson, you'll be able to create complex functional objects, apply them to collections using Boost.Range, and understand the benefits of such an approach.

Setting Up

We start by defining a struct for employees:

struct Employee {
    std::string name;
    double salary;
};

This structure holds basic details about an employee, which include their name and salary.

Defining a Functional Object

Let's create a functor that increases salary by a certain factor:

struct SalaryIncrease {
    double factor;
   SalaryIncrease(double f) : factor(f) {}

    double operator()(const Employee& emp) const {
        return emp.salary * factor;
    }
};

In this example:

  • The constructor SalaryIncrease(double f) initializes the factor used to increase the salary.
  • The operator() takes an Employee object and returns the new salary by multiplying the current one with the factor.

Using Functional Objects in a Program

Let's integrate the Employee and SalaryIncrease functor into a simple program. We need a collection of employees. We'll use a std::vector:

std::vector<Employee> employees = {
    {"Alice", 30000},
    {"Bob", 45000},
    {"Charlie", 32000},
    {"David", 52000},
    {"Eve", 48000}
};

To apply the 10% salary increase, we instantiate the SalaryIncrease functor:

double increaseFactor = 1.1; // 10% raise
SalaryIncrease increase(increaseFactor);

Applying the Functor with Boost.Range

Boost.Range is a powerful library for working with ranges in a way that feels natural and expressive. We'll use it to apply our salary increase functor to each employee in our vector.

We use Boost's transformed adaptor to apply our functor:

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/for_each.hpp>

auto increased_salaries = employees | boost::adaptors::transformed([&increase](const Employee& emp) {
    return Employee{emp.name, increase(emp)};
});

In this code:

  • boost::adaptors::transformed applies our functor to each element in the range.
  • The lambda function [&increase](const Employee& emp) captures the functor and applies it to each Employee.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal