Menu
Coddy logo textTech

Foncteurs et expressions lambda

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 74 sur 104.

De nombreux algorithmes de la STL acceptent un objet appelable qui personnalise leur comportement. Tu as déjà vu des lambdas utilisées avec std::transform. Explorons à la fois les functors et les expressions lambda — deux façons de créer des objets appelables en C++.

Un functor (objet fonction) est une class qui surcharge l’operator(), ce qui permet d’appeler ses instances comme des fonctions :

#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}
}

Chaque instance de foncteur peut conserver son propre état indépendant grâce à des variables membres définies lors de la construction — ce qu’un appel de fonction ordinaire ne peut pas faire. Cependant, définir une class pour des opérations simples est verbeux. Les expressions lambda offrent une alternative concise :

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

La syntaxe lambda est [capture](parameters) { body }. La clause de capture précise quelles variables externes la lambda peut accéder. Utilisez [=] pour capturer toutes les variables par valeur, [&] pour toutes les capturer par référence, ou indiquez des variables spécifiques comme [factor] ou [&factor].

Les lambdas sont particulièrement utiles pour les opérations ponctuelles avec des algorithmes comme le tri selon des critères personnalisés :

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); });
// Trié par valeur absolue : {-1, -2, 5, 8}
challenge icon

Défi

Facile

Construisons un calculateur de prix qui présente à la fois les foncteurs et les expressions lambda pour appliquer différentes stratégies de remise aux prix des produits.

Vous organiserez votre code sur deux fichiers :

  • Discounts.h : Définissez ici vos foncteurs de remise et vos fonctions utilitaires.

    Créez un foncteur appelé PercentageDiscount qui stocke un pourcentage de remise (sous forme d'entier). Son operator() doit prendre un prix de type double et renvoyer le prix remisé. Par exemple, une remise de 20 % sur 100 $ doit renvoyer 80 $.

    Créez un autre foncteur appelé FixedDiscount qui stocke un montant fixe à soustraire (sous forme de double). Son operator() doit prendre un prix et renvoyer le prix moins le montant fixe (mais never inférieur à 0).

    Créez une fonction appelée printPrices qui prend un const std::vector<double>& et affiche tous les prix séparés par des espaces, suivis d'une nouvelle ligne. Formatez chaque prix avec deux décimales.

  • main.cpp : Lisez cinq entrées (chacune sur une ligne distincte) :
    1. Prix du premier produit (double)
    2. Prix du deuxième produit (double)
    3. Prix du troisième produit (double)
    4. Remise en pourcentage à appliquer (entier, par exemple 20 pour 20 %)
    5. Montant de la remise fixe (double)

    Créez un vecteur avec les trois prix et présentez les deux approches :

    1. Affichez Original prices: suivi des prix
    2. Utilisez std::transform avec votre foncteur PercentageDiscount pour créer un nouveau vecteur de prix remisés. Affichez After percentage discount: suivi des résultats
    3. Utilisez std::transform avec votre foncteur FixedDiscount sur les prix originaux pour créer un autre vecteur. Affichez After fixed discount: suivi des résultats
    4. Utilisez std::transform avec une expression lambda qui double chaque prix original. Affichez Premium prices (doubled): suivi des résultats
    5. Utilisez std::sort avec une lambda pour trier les prix originaux dans l'ordre descending. Affichez Sorted (high to low): suivi des prix triés

Par exemple, avec les entrées 100.00, 50.00, 75.00, 20 et 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 

Ce défi vous permet de comparer les foncteurs (qui conservent un état tel que le montant de la remise) avec les lambdas (qui capturent des variables pour des opérations rapides et intégrées). Les deux approches fonctionnent parfaitement avec les algorithmes STL tels que std::transform et std::sort.

Essayez vous-même

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

int main() {
    // Lire les entrées
    double price1, price2, price3;
    int percentageDiscount;
    double fixedDiscount;
    
    std::cin >> price1;
    std::cin >> price2;
    std::cin >> price3;
    std::cin >> percentageDiscount;
    std::cin >> fixedDiscount;
    
    // Créer un vecteur avec les trois prix
    std::vector<double> prices = {price1, price2, price3};
    
    // TODO: Print "Original prices:" followed by the prices using printPrices
    
    // TODO: Use std::transform with PercentageDiscount functor
    // Créer un nouveau vecteur pour les résultats
    // Print "After percentage discount:" followed by the results
    
    // TODO: Use std::transform with FixedDiscount functor on original prices
    // Créer un nouveau vecteur pour les résultats
    // Print "After fixed discount:" followed by the results
    
    // TODO: Use std::transform with a lambda that doubles each original price
    // Créer un nouveau vecteur pour les résultats
    // 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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne