Menu
Coddy logo textTech

Structured Bindings

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 88 de 104.

Structured bindings, introduzidas no C++17, permitem desempacotar múltiplos valores de arrays, pairs, tuples ou structs em variáveis nomeadas individuais em uma única declaração. Isso torna o código mais limpo e legível ao trabalhar com dados compostos.

A sintaxe usa auto com colchetes contendo os novos nomes de variáveis:

#include <iostream>
#include <map>
#include <tuple>

int main() {
    // Desempacotando um pair
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // Desempacotando uma tupla
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // Desempacotando em loops for baseados em intervalo
    std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
    for (const auto& [student, score] : scores) {
        std::cout << student << ": " << score << "\n";
    }
}

Structured bindings também funcionam com arrays e structs personalizadas que possuem membros públicos:

struct Point {
    double x;
    double y;
};

Point getOrigin() { return {0.0, 0.0}; }

int main() {
    auto [x, y] = getOrigin();
    
    int arr[3] = {1, 2, 3};
    auto [a, b, c] = arr;
}

Você pode usar auto& ou const auto& para vincular por referência, evitando cópias e permitindo a modificação dos valores originais quando necessário. Este recurso é especialmente útil ao iterar sobre containers STL ou ao lidar com funções que retornam múltiplos valores.

challenge icon

Desafio

Fácil

Vamos construir um analisador de notas de alunos que demonstra o poder dos structured bindings. Você criará um sistema que processa registros de alunos e dados de cursos, usando structured bindings para desempacotar elegantemente pairs, tuples e structs em todo o seu código.

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

  • Student.h: Defina uma struct Student com membros públicos para o nome do aluno (std::string), ID (int) e GPA (double). Também crie uma função chamada createStudent que recebe um nome, ID e GPA, e retorna uma struct Student.
  • GradeUtils.h: Crie funções utilitárias para o processamento de notas.

    Defina uma função getGradeInfo que recebe uma pontuação numérica (inteiro) e retorna um std::tuple contendo três valores: a nota em letra (std::string), os pontos da nota (double) e se foi aprovado (bool). Use esta escala de notas:

    • 90+ : "A", 4.0, true
    • 80-89: "B", 3.0, true
    • 70-79: "C", 2.0, true
    • 60-69: "D", 1.0, true
    • Abaixo de 60: "F", 0.0, false

    Também defina uma função makeScorePair que recebe um nome de curso (std::string) e uma pontuação (int), retornando um std::pair desses valores.

  • main.cpp: Leia quatro entradas:
    1. Nome do aluno (string)
    2. ID do aluno (inteiro)
    3. Nome do curso (string)
    4. Pontuação (inteiro)

    Use structured bindings em toda a sua função main:

    1. Chame createStudent com o nome, ID e um GPA de espaço reservado de 0.0. Use structured bindings para desempacotar a struct retornada em variáveis individuais e, em seguida, imprima: Student: [name] (ID: [id])
    2. Chame makeScorePair com o nome do curso e a pontuação. Use structured bindings para desempacotar o pair e, em seguida, imprima: Course: [course], Score: [score]
    3. Chame getGradeInfo com a pontuação. Use structured bindings para desempacotar todos os três elementos da tupla e, em seguida, imprima:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (Imprima "yes" se passing for true, "no" se for false)

Por exemplo, com as entradas Alice, 1001, Math e 85:

Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yes

Com as entradas Bob, 2002, Physics, and 55:

Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: no

Lembre-se de incluir <tuple> e <utility> onde for necessário. O ponto principal é como os structured bindings permitem desempacotar tipos compostos — pairs, tuples e structs — em variáveis nomeadas em uma única declaração legível.

Folha de consulta

Structured bindings (C++17) permitem desempacotar múltiplos valores de arrays, pairs, tuples ou structs em variáveis nomeadas individuais em uma única declaração.

A sintaxe básica utiliza auto com colchetes:

auto [var1, var2, ...] = composite_object;

Desempacotando um std::pair:

std::pair<std::string, int> person{"Alice", 25};
auto [name, age] = person;

Desempacotando um std::tuple:

std::tuple<int, double, char> data{42, 3.14, 'X'};
auto [num, pi, letter] = data;

Usando structured bindings em loops for baseados em intervalo (range-based for loops) com containers como std::map:

std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
for (const auto& [student, score] : scores) {
    std::cout << student << ": " << score << "\n";
}

Desempacotando structs com membros públicos:

struct Point {
    double x;
    double y;
};

Point getOrigin() { return {0.0, 0.0}; }

auto [x, y] = getOrigin();

Desempacotando arrays:

int arr[3] = {1, 2, 3};
auto [a, b, c] = arr;

Use auto& ou const auto& para vincular por referência, evitando cópias e permitindo a modificação dos valores originais:

auto& [x, y] = point;  // Pode modificar o original
const auto& [name, age] = person;  // Referência apenas de leitura

Experimente você mesmo

#include <iostream>
#include <string>
#include "Student.h"
#include "GradeUtils.h"

int main() {
    // Ler as entradas
    std::string studentName;
    int studentId;
    std::string courseName;
    int score;
    
    std::cin >> studentName;
    std::cin >> studentId;
    std::cin >> courseName;
    std::cin >> score;
    
    // TODO: Chamar createStudent com name, id e um GPA reservado de 0.0
    // Usar structured bindings para desempacotar a struct: auto [name, id, gpa] = ...
    // Imprimir: Student: [name] (ID: [id])
    
    
    // TODO: Chamar makeScorePair com course name e score
    // Usar structured bindings para desempacotar o pair: auto [course, sc] = ...
    // Imprimir: Course: [course], Score: [score]
    
    
    // TODO: Chamar getGradeInfo com o score
    // Usar structured bindings para desempacotar a tuple: auto [letter, points, passing] = ...
    // Imprimir:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no] (imprimir "yes" se passing for true, "no" se for false)
    
    
    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