Menu
Coddy logo textTech

std::function e std::bind

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 86 de 104.

Embora as lambdas sejam poderosas, às vezes você precisa armazenar objetos chamáveis de tipos diferentes de maneira uniforme ou adaptar funções existentes para corresponder a uma assinatura necessária. std::function e std::bind do cabeçalho <functional> resolvem esses problemas.

std::function é um wrapper com apagamento de tipo que pode armazenar qualquer objeto chamável compatível com uma assinatura específica — funções, lambdas ou objetos de função:

#include <iostream>
#include <functional>

int add(int a, int b) { return a + b; }

int main() {
    std::function<int(int, int)> operation;
    
    operation = add;                              // Função regular
    std::cout << operation(3, 4) << "\n";        // 7
    
    operation = [](int a, int b) { return a * b; }; // Lambda
    std::cout << operation(3, 4) << "\n";        // 12
}

std::bind cria um novo objeto chamável ao fixar alguns argumentos de uma função existente. Use std::placeholders::_1, _2, etc. para marcar os argumentos que permanecem variáveis:

#include <iostream>
#include <functional>

void greet(const std::string& greeting, const std::string& name) {
    std::cout << greeting << ", " << name << "!\n";
}

int main() {
    using namespace std::placeholders;
    
    auto sayHello = std::bind(greet, "Hello", _1);
    sayHello("Alice");  // Olá, Alice!
    
    auto swapped = std::bind(greet, _2, _1);
    swapped("Bob", "Hi");  // Oi, Bob!
}

Essas ferramentas são especialmente úteis em POO para armazenar callbacks como membros de classes ou implementar o padrão Strategy. No entanto, o C++ moderno geralmente prefere lambdas a std::bind por oferecerem melhor legibilidade e desempenho — use std::bind principalmente quando precisar reordenar argumentos ou trabalhar com código legado.

challenge icon

Desafio

Fácil

Vamos criar uma calculadora configurável que demonstra o poder de std::function e std::bind. Você criará um sistema no qual as operações matemáticas podem ser armazenadas, trocadas e personalizadas em tempo de execução, mostrando como essas ferramentas permitem um gerenciamento flexível de callbacks.

Você organizará seu código em três arquivos:

  • MathOperations.h: defina uma coleção de funções matemáticas independentes que servirão como sua biblioteca de operações.

    Crie estas funções:

    • add(int a, int b): retorna a soma
    • subtract(int a, int b): retorna a diferença (a - b)
    • multiply(int a, int b): retorna o produto
    • power(int base, int exponent, int multiplier): retorna multiplier * (base ^ exponent). Use um loop simples para calcular a potência (considere expoentes não negativos).
  • Calculator.h: defina uma classe Calculator que use std::function para armazenar e executar operações dinamicamente.

    Seu Calculator deve ter:

    • Um membro privado std::function<int(int, int)> para armazenar a operação binária atual
    • setOperation(std::function<int(int, int)> op): define a operação atual
    • calculate(int a, int b): executa a operação armazenada e retorna o resultado

    Inclua os cabeçalhos necessários (<functional>) e certifique-se de incluir seu cabeçalho MathOperations.

  • main.cpp: leia três entradas:
    1. Nome da operação: add, subtract, multiply ou square
    2. Primeiro número (inteiro)
    3. Segundo número (inteiro)

    Crie um Calculator e configure-o com base no nome da operação:

    • Para add, subtract e multiply: atribua diretamente a função correspondente à calculadora
    • Para square: use std::bind para criar uma versão especializada de power que sempre use expoente 2 e multiplicador 1. A função vinculada deve aceitar dois argumentos, dos quais apenas o primeiro é usado como base (o segundo argumento pode ser ignorado usando um placeholder).

    Depois de definir a operação, chame calculate() com seus dois números e imprima:

    Result: [value]

    Em seguida, demonstre a troca de operações atribuindo à calculadora uma lambda que retorna a + b + 100, executando-a com as mesmas entradas e imprimindo:

    With bonus: [value]

Por exemplo, com as entradas add, 10 e 5:

Result: 15
With bonus: 115

Com as entradas multiply, 7 e 3:

Result: 21
With bonus: 110

Com as entradas square, 4 e 0:

Result: 16
With bonus: 104

Este desafio mostra como std::function fornece uma maneira uniforme de armazenar diferentes tipos chamáveis (funções regulares, funções vinculadas e lambdas), enquanto std::bind permite adaptar funções existentes fixando alguns de seus argumentos.

Experimente você mesmo

#include <iostream>
#include <string>
#include <functional>
#include "Calculator.h"

using namespace std;

int main() {
    // Ler entradas
    string operation;
    int num1, num2;
    cin >> operation >> num1 >> num2;
    
    // Criar uma instância de Calculator
    Calculator calc;
    
    // TODO: Configure a calculadora com base no nome da operação
    // Para "add", "subtract", "multiply": atribua a função correspondente diretamente
    // Para "square": use std::bind para criar uma versão especializada de power
    //   que sempre usa expoente 2 e multiplicador 1
    //   Dica: Use std::placeholders::_1 para o argumento base
    
    if (operation == "add") {
        // Seu código aqui
    } else if (operation == "subtract") {
        // Seu código aqui
    } else if (operation == "multiply") {
        // Seu código aqui
    } else if (operation == "square") {
        // Seu código aqui - use std::bind com a função power
    }
    
    // TODO: Chame calculate() e imprima o resultado
    // Formato: "Result: [value]"
    
    // TODO: Demonstre a troca de operações
    // Atribua uma lambda que retorna a + b + 100 ao calculator
    // Chame calculate() novamente e imprima o resultado
    // Formato: "With bonus: [value]"
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de C++ online