Menu
Coddy logo textTech

Структурированные привязки

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 88 из 104.

Structured bindings, появившиеся в C++17, позволяют распаковывать несколько значений из массивов, пар, кортежей или структур в отдельные именованные переменные в одном объявлении. Это делает код более чистым и понятным при работе с составными данными.

В синтаксисе используется auto с квадратными скобками, содержащими новые имена переменных:

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

int main() {
    // Распаковка пары
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // Распаковка кортежа
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // Распаковка в range-based for-циклах
    std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
    for (const auto& [student, score] : scores) {
        std::cout << student << ": " << score << "\n";
    }
}

Структурированные привязки также работают с массивами и пользовательскими структурами, у которых есть общедоступные члены:

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

Вы можете использовать auto& или const auto&, чтобы связать по ссылке, избегая копирования и позволяя изменять исходные значения при необходимости. Эта возможность особенно полезна при переборе контейнеров STL или обработке функций, возвращающих несколько значений.

challenge icon

Задание

Легко

Давайте создадим анализатор оценок студентов, демонстрирующий возможности структурированных привязок. Вы создадите систему, которая обрабатывает записи студентов и данные курсов, используя структурированные привязки для элегантной распаковки пар, кортежей и структур по всему коду.

Вы организуете код в трёх файлах:

  • Student.h: Define структуру Student с открытыми членами для имени студента (std::string), идентификатора (int) и GPA (double). Также создайте функцию с именем createStudent, которая принимает имя, идентификатор и GPA и возвращает структуру Student.
  • GradeUtils.h: Создайте вспомогательные функции для обработки оценок.

    Define функцию getGradeInfo, которая принимает numeric оценку (целое число) и возвращает std::tuple, содержащий три значения: буквенную оценку (std::string), баллы за оценку (double) и признак того, является ли оценка проходной (bool). Используйте следующую шкалу оценок:

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

    Также Define функцию makeScorePair, которая принимает название курса (std::string) и оценку (int), возвращая std::pair из этих значений.

  • main.cpp: Считайте четыре входных значения:
    1. Имя студента (строка)
    2. Идентификатор студента (целое число)
    3. Название курса (строка)
    4. Оценка (целое число)

    Используйте структурированные привязки на протяжении всей функции main:

    1. Вызовите createStudent с именем, идентификатором и placeholder GPA, равным 0.0. Используйте структурированные привязки, чтобы распаковать возвращённую структуру в отдельные переменные, а затем выведите: Student: [name] (ID: [id])
    2. Вызовите makeScorePair с названием курса и оценкой. Используйте структурированные привязки, чтобы распаковать пару, а затем выведите: Course: [course], Score: [score]
    3. Вызовите getGradeInfo с оценкой. Используйте структурированные привязки, чтобы распаковать все три элемента кортежа, а затем выведите:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (Выведите "yes", если passing имеет значение true, и "no", если false)

Например, для входных данных Alice, 1001, Math и 85:

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

Для входных данных Bob, 2002, Physics и 55:

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

Не забудьте добавить <tuple> и <utility> там, где это необходимо. Основная идея заключается в том, как структурированные привязки позволяют распаковывать составные типы, пары, кортежи и структуры в именованные переменные в одном понятном объявлении.

Попробуйте сами

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

int main() {
    // Прочитать входные данные
    std::string studentName;
    int studentId;
    std::string courseName;
    int score;
    
    std::cin >> studentName;
    std::cin >> studentId;
    std::cin >> courseName;
    std::cin >> score;
    
    // TODO: Вызвать createStudent с name, id и временным GPA 0.0
    // Используйте структурированные привязки для распаковки структуры: auto [name, id, gpa] = ...
    // Вывести: Student: [name] (ID: [id])
    
    
    // TODO: Вызвать makeScorePair с названием курса и score
    // Используйте структурированные привязки для распаковки пары: auto [course, sc] = ...
    // Вывести: Course: [course], Score: [score]
    
    
    // TODO: Вызвать getGradeInfo с score
    // Используйте структурированные привязки для распаковки кортежа: auto [letter, points, passing] = ...
    // Вывести:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no] (выведите "yes", если passing равно true, "no", если false)
    
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++