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.
Desafío
FácilVamos 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 estructuraStudentcon miembros públicos para el nombre del estudiante (std::string), ID (int) y GPA (double). También crea una función llamadacreateStudentque reciba un nombre, ID y GPA, y devuelva una estructuraStudent.GradeUtils.h: Crea funciones de utilidad para el procesamiento de calificaciones.Define una función
getGradeInfoque reciba una puntuación numérica (entero) y devuelva unstd::tupleque 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
makeScorePairque reciba un nombre de curso (std::string) y una puntuación (int), devolviendo unstd::paircon esos valores.main.cpp: Lee cuatro entradas:- Nombre del estudiante (string)
- ID del estudiante (entero)
- Nombre del curso (string)
- Puntuación (entero)
Utiliza structured bindings a lo largo de tu función principal:
- Llama a
createStudentcon 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]) - Llama a
makeScorePaircon el nombre del curso y la puntuación. Usa structured bindings para desempaquetar el par, luego imprime:Course: [course], Score: [score] - Llama a
getGradeInfocon la puntuación. Usa structured bindings para desempaquetar los tres elementos de la tupla, luego imprime:(Imprime "yes" si passing es true, "no" si es false)Grade: [letter] Points: [points] Passing: [yes/no]
Por ejemplo, con las entradas Alice, 1001, Math y 85:
Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yesCon las entradas Bob, 2002, Physics y 55:
Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: noRecuerda 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 lecturaPrué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;
}
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
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genérico12Características de C++ moderno
Semántica de movimiento y RvaluesReenvío perfectoExpresiones Lambda en profundidadstd::function y std::bindconstexpr y constevalBindings estructuradosoptional, variant, any