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 las 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 functor puede llevar su propio estado independiente mediante variables miembro establecidas durante la construcción, algo que una llamada a una function ordinaria no puede hacer. Sin embargo, definir una class para operaciones simples resulta demasiado verboso. Las expresiones lambda proporcionan 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 captarlas todas por valor, [&] para captarlas 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 functors como las expresiones lambda para aplicar distintas estrategias de descuento a los precios de productos.

Organizarás tu código en dos archivos:

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

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

    Create 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 never por debajo de 0).

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

  • main.cpp: Lee cinco inputs (cada uno 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á (integer, por ejemplo, 20 para 20%)
    5. Cantidad del descuento fijo (double)

    Create 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 vector nuevo de precios con descuento. Imprime After percentage discount: seguido de los resultados
    3. Usa std::transform con tu functor FixedDiscount sobre los precios original para crear otro vector. Imprime After fixed discount: seguido de los resultados
    4. Usa std::transform con una expresión lambda que doubles cada precio original. Imprime Premium prices (doubled): seguido de los resultados
    5. Usa std::sort con una lambda para ordenar los precios original en order descending. Imprime Sorted (high to low): seguido de los precios ordenados

Por ejemplo, con los inputs 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 functors (que mantienen el estado, como la cantidad del descuento) con lambdas (que capturan variables para realizar operaciones rápidas y en línea). Ambos enfoques funcionan perfectamente con algoritmos 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