Menu
Coddy logo textTech

Bindings estructurados

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 88 de 104.

Structured bindings, introducidos en C++17, permiten desempaquetar múltiples valores de arreglos, pares, tuplas o estructuras en variables con nombre individuales en una sola declaración. Esto hace que el código sea más limpio y legible al trabajar con datos compuestos.

La sintaxis utiliza auto con corchetes que contienen los nuevos nombres de las variables:

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

int main() {
    // Desempaquetando un par
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // Desempaquetando una tupla
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // Desempaquetando en bucles for basados en rangos
    std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
    for (const auto& [student, score] : scores) {
        std::cout << student << ": " << score << "\n";
    }
}

Los enlaces estructurados también funcionan con arreglos y estructuras personalizadas que tienen miembros 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;
}

Puedes usar auto& o const auto& para vincular por referencia, evitando copias y permitiendo la modificación de los valores originales cuando sea necesario. Esta característica es especialmente útil al iterar sobre contenedores STL o al manejar funciones que devuelven múltiples valores.

challenge icon

Desafío

Fácil

Vamos a construir un analizador de calificaciones de estudiantes que demuestre el poder de los structured bindings. Crearás un sistema que procesa registros de estudiantes y datos de cursos, utilizando structured bindings para desempaquetar elegantemente pares, tuplas y estructuras a lo largo de tu código.

Organizarás tu código en tres archivos:

  • Student.h: Define una estructura Student con miembros públicos para el nombre del estudiante (std::string), ID (int) y GPA (double). También crea una función llamada createStudent que reciba un nombre, ID y GPA, y devuelva una estructura Student.
  • GradeUtils.h: Crea funciones de utilidad para el procesamiento de calificaciones.

    Define una función getGradeInfo que reciba una puntuación numérica (entero) y devuelva un std::tuple que contenga tres valores: la letra de la calificación (std::string), los puntos de la calificación (double) y si es aprobatoria (bool). Utiliza esta escala de calificación:

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

    También define una función makeScorePair que reciba un nombre de curso (std::string) y una puntuación (int), devolviendo un std::pair con esos valores.

  • main.cpp: Lee cuatro entradas:
    1. Nombre del estudiante (string)
    2. ID del estudiante (entero)
    3. Nombre del curso (string)
    4. Puntuación (entero)

    Utiliza structured bindings a lo largo de tu función principal:

    1. Llama a createStudent con el nombre, ID y un GPA de marcador de posición de 0.0. Usa structured bindings para desempaquetar la estructura devuelta en variables individuales, luego imprime: Student: [name] (ID: [id])
    2. Llama a makeScorePair con el nombre del curso y la puntuación. Usa structured bindings para desempaquetar el par, luego imprime: Course: [course], Score: [score]
    3. Llama a getGradeInfo con la puntuación. Usa structured bindings para desempaquetar los tres elementos de la tupla, luego imprime:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (Imprime "yes" si passing es true, "no" si es false)

Por ejemplo, con las entradas Alice, 1001, Math y 85:

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

Con las entradas Bob, 2002, Physics y 55:

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

Recuerda incluir <tuple> y <utility> donde sea necesario. La idea clave es cómo los structured bindings te permiten desempaquetar tipos compuestos (pares, tuplas y estructuras) en variables con nombre en una sola declaración legible.

Hoja de referencia

Los enlaces estructurados (C++17) permiten desempaquetar múltiples valores de arreglos, pares, tuplas o estructuras en variables con nombre individuales en una sola declaración.

La sintaxis básica utiliza auto con corchetes:

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

Desempaquetando un std::pair:

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

Desempaquetando un std::tuple:

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

Uso de enlaces estructurados en bucles for basados en rangos con contenedores como std::map:

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

Desempaquetando estructuras con miembros públicos:

struct Point {
    double x;
    double y;
};

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

auto [x, y] = getOrigin();

Desempaquetando arreglos:

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

Use auto& o const auto& para vincular por referencia, evitando copias y permitiendo la modificación de los valores originales:

auto& [x, y] = point;  // Puede modificar el original
const auto& [name, age] = person;  // Referencia de solo lectura

Pruébalo tú mismo

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

int main() {
    // Leer entradas
    std::string studentName;
    int studentId;
    std::string courseName;
    int score;
    
    std::cin >> studentName;
    std::cin >> studentId;
    std::cin >> courseName;
    std::cin >> score;
    
    // TODO: Llamar a createStudent con name, id, y un GPA de marcador de posición de 0.0
    // Usar structured bindings para desempaquetar el struct: auto [name, id, gpa] = ...
    // Imprimir: Student: [name] (ID: [id])
    
    
    // TODO: Llamar a makeScorePair con course name y score
    // Usar structured bindings para desempaquetar el pair: auto [course, sc] = ...
    // Imprimir: Course: [course], Score: [score]
    
    
    // TODO: Llamar a getGradeInfo con el score
    // Usar structured bindings para desempaquetar la tuple: auto [letter, points, passing] = ...
    // Imprimir:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no] (imprimir "yes" si passing es true, "no" si es false)
    
    
    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