Menu
Coddy logo textTech

Funtores y expresiones lambda

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 74 de 104.

Muchos algoritmos de STL aceptan un objeto invocable que personaliza su comportamiento. Ya has visto lambdas utilizadas con std::transform. Exploremos tanto los functors como las expresiones lambda: dos formas de crear objetos invocables en C++.

Un functor (objeto función) es una clase que sobrecarga el operator(), lo que permite llamar a sus instancias como funciones:

#include <algorithm>
#include <vector>
#include <iostream>

struct MultiplyBy {
    int factor;
    MultiplyBy(int f) : factor(f) {}
    
    int operator()(int x) const {
        return x * factor;
    }
};

int main() {
    std::vector<int> nums = {1, 2, 3, 4};
    std::vector<int> result(nums.size());
    
    std::transform(nums.begin(), nums.end(), result.begin(), MultiplyBy(3));
    // result: {3, 6, 9, 12}
}

Cada instancia de un functor puede mantener su propio estado independiente mediante variables miembro establecidas durante la construcción, algo que una llamada a una función ordinaria no puede hacer. Sin embargo, definir una clase para operaciones sencillas resulta verboso. Las expresiones lambda ofrecen una alternativa concisa:

int factor = 3;
std::transform(nums.begin(), nums.end(), result.begin(),
               [factor](int x) { return x * factor; });

La sintaxis de lambda es [capture](parameters) { body }. La cláusula de captura especifica a qué variables externas puede acceder la lambda. Usa [=] para capturarlas todas por valor, [&] para capturarlas todas por referencia, o enumera variables específicas como [factor] o [&factor].

Las lambdas son especialmente útiles para operaciones puntuales con algoritmos como la ordenación con criterios personalizados:

std::vector<int> nums = {5, -2, 8, -1};
std::sort(nums.begin(), nums.end(), 
          [](int a, int b) { return std::abs(a) < std::abs(b); });
// Ordenado por valor absoluto: {-1, -2, 5, 8}
challenge icon

Desafío

Fácil

Construyamos una calculadora de precios que demuestre tanto los funtores como las expresiones lambda para aplicar distintas estrategias de descuento a los precios de los productos.

Organizarás tu código en dos archivos:

  • Discounts.h: Define aquí tus funtores de descuento y funciones auxiliares.

    Crea un functor llamado PercentageDiscount que almacene un porcentaje de descuento (como un entero). Su operator() debe recibir un precio double y devolver el precio con descuento. Por ejemplo, un descuento del 20 % sobre $100 debe devolver $80.

    Crea otro functor llamado FixedDiscount que almacene una cantidad fija para restar (como un double). Su operator() debe recibir un precio y devolver el precio menos la cantidad fija (pero nunca un valor inferior a 0).

    Crea una función llamada printPrices que reciba un const std::vector<double>& e imprima todos los precios separados por espacios, seguidos de un salto de línea. Da formato a cada precio con dos decimales.

  • main.cpp: Lee cinco entradas (cada una en una línea separada):
    1. Precio del primer producto (double)
    2. Precio del segundo producto (double)
    3. Precio del tercer producto (double)
    4. Descuento porcentual que se aplicará (entero, por ejemplo, 20 para 20 %)
    5. Cantidad del descuento fijo (double)

    Crea un vector con los tres precios y demuestra ambos enfoques:

    1. Imprime Original prices: seguido de los precios
    2. Usa std::transform con tu functor PercentageDiscount para crear un nuevo vector de precios con descuento. Imprime After percentage discount: seguido de los resultados
    3. Usa std::transform con tu functor FixedDiscount sobre los precios originales para crear otro vector. Imprime After fixed discount: seguido de los resultados
    4. Usa std::transform con una expresión lambda que duplique cada precio original. Imprime Premium prices (doubled): seguido de los resultados
    5. Usa std::sort con una lambda para ordenar los precios originales en orden descendente. Imprime Sorted (high to low): seguido de los precios ordenados

Por ejemplo, con las entradas 100.00, 50.00, 75.00, 20 y 15.00:

Original prices: 100.00 50.00 75.00 
After percentage discount: 80.00 40.00 60.00 
After fixed discount: 85.00 35.00 60.00 
Premium prices (doubled): 200.00 100.00 150.00 
Sorted (high to low): 100.00 75.00 50.00 

Este desafío te permite comparar los funtores (que mantienen un estado, como la cantidad del descuento) con las lambdas (que capturan variables para realizar operaciones rápidas en línea). Ambos enfoques funcionan perfectamente con algoritmos de STL como std::transform y std::sort.

Pruébalo tú mismo

#include <iostream>
#include <vector>
#include <algorithm>
#include "Discounts.h"

int main() {
    // Leer entradas
    double price1, price2, price3;
    int percentageDiscount;
    double fixedDiscount;
    
    std::cin >> price1;
    std::cin >> price2;
    std::cin >> price3;
    std::cin >> percentageDiscount;
    std::cin >> fixedDiscount;
    
    // Crear un vector con los tres precios
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: Print "Original prices:" followed by the prices using printPrices
    
    // TODO: Use std::transform with PercentageDiscount functor
    // Crear un nuevo vector para los resultados
    // Print "After percentage discount:" followed by the results
    
    // TODO: Use std::transform with FixedDiscount functor on original prices
    // Crear un nuevo vector para los resultados
    // Print "After fixed discount:" followed by the results
    
    // TODO: Use std::transform with a lambda that doubles each original price
    // Crear un nuevo vector para los resultados
    // Print "Premium prices (doubled):" followed by the results
    
    // TODO: Use std::sort with a lambda to sort original prices in descending order
    // Print "Sorted (high to low):" followed by the sorted prices
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online