Menu
Coddy logo textTech

구조화된 바인딩

Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 88번째.

C++17에서 도입된 구조적 바인딩(Structured bindings)을 사용하면 배열, pair, tuple 또는 구조체에서 여러 값을 단일 선언으로 개별 명명된 변수에 풀어서 넣을 수 있습니다. 이는 복합 데이터를 다룰 때 코드를 더 깔끔하고 가독성 있게 만들어 줍니다.

구문은 새로운 변수 이름을 포함하는 대괄호와 함께 auto를 사용합니다:

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

int main() {
    // pair 언패킹
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // tuple 언패킹
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // 범위 기반 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

챌린지

쉬움

구조화된 바인딩(structured bindings)의 강력함을 보여주는 학생 성적 분석기를 만들어 봅시다. 여러분은 학생 기록과 과목 데이터를 처리하는 시스템을 만들게 되며, 코드 전반에서 구조화된 바인딩을 사용하여 pair, tuple, struct를 우아하게 언팩(unpack)하는 방법을 배우게 됩니다.

코드는 다음 세 개의 파일로 구성됩니다:

  • Student.h: 학생의 이름(std::string), ID(int), GPA(double)를 공용 멤버로 가지는 Student 구조체를 정의합니다. 또한 이름, ID, GPA를 매개변수로 받아 Student 구조체를 반환하는 createStudent 함수를 작성합니다.
  • GradeUtils.h: 성적 처리를 위한 유틸리티 함수들을 작성합니다.

    숫자 점수(정수)를 입력받아 세 가지 값, 즉 문자 성적(std::string), 등급 점수(double), 합격 여부(bool)를 포함하는 std::tuple을 반환하는 getGradeInfo 함수를 정의합니다. 다음 성적 기준을 사용하세요:

    • 90점 이상 : "A", 4.0, true
    • 80-89점: "B", 3.0, true
    • 70-79점: "C", 2.0, true
    • 60-69점: "D", 1.0, true
    • 60점 미만: "F", 0.0, false

    또한 과목 이름(std::string)과 점수(int)를 입력받아 이 값들의 std::pair를 반환하는 makeScorePair 함수를 정의합니다.

  • main.cpp: 네 개의 입력을 읽습니다:
    1. 학생 이름 (문자열)
    2. 학생 ID (정수)
    3. 과목 이름 (문자열)
    4. 점수 (정수)

    main 함수 전체에서 구조화된 바인딩을 사용하세요:

    1. 이름, ID, 그리고 임시 GPA 값인 0.0을 사용하여 createStudent를 호출합니다. 구조화된 바인딩을 사용하여 반환된 구조체를 개별 변수로 언팩한 후, 다음과 같이 출력합니다: Student: [name] (ID: [id])
    2. 과목 이름과 점수를 사용하여 makeScorePair를 호출합니다. 구조화된 바인딩을 사용하여 pair를 언팩한 후, 다음과 같이 출력합니다: Course: [course], Score: [score]
    3. 점수를 사용하여 getGradeInfo를 호출합니다. 구조화된 바인딩을 사용하여 튜플의 세 요소를 모두 언팩한 후, 다음과 같이 출력합니다:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (합격 여부가 true이면 "yes"를, false이면 "no"를 출력합니다)

예를 들어, 입력값이 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>를 포함하는 것을 잊지 마세요. 이번 과제의 핵심은 구조화된 바인딩을 통해 pair, tuple, struct와 같은 복합 타입을 단일하고 가독성 있는 선언으로 이름이 있는 변수들로 언팩하는 방법을 익히는 것입니다.

치트 시트

구조체 바인딩(C++17)을 사용하면 배열, pair, tuple 또는 구조체에서 여러 값을 단일 선언으로 개별 명명된 변수로 언패킹할 수 있습니다.

기본 구문은 대괄호와 함께 auto를 사용합니다:

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

std::pair 언패킹:

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

std::tuple 언패킹:

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

std::map과 같은 컨테이너와 함께 범위 기반 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}; }

auto [x, y] = getOrigin();

배열 언패킹:

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

참조로 바인딩하려면 auto& 또는 const auto&를 사용하세요. 이를 통해 복사를 방지하고 원본 값을 수정할 수 있습니다:

auto& [x, y] = point;  // 원본 수정 가능
const auto& [name, age] = person;  // 읽기 전용 참조

직접 해보기

#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: name, id, 그리고 GPA의 자리 표시자로 0.0을 사용하여 createStudent 호출
    // 구조 분해 할당(structured bindings)을 사용하여 구조체 언팩: auto [name, id, gpa] = ...
    // 출력: Student: [name] (ID: [id])
    
    
    // TODO: course name과 score를 사용하여 makeScorePair 호출
    // 구조 분해 할당(structured bindings)을 사용하여 pair 언팩: auto [course, sc] = ...
    // 출력: Course: [course], Score: [score]
    
    
    // TODO: score를 사용하여 getGradeInfo 호출
    // 구조 분해 할당(structured bindings)을 사용하여 튜플 언팩: auto [letter, points, passing] = ...
    // 출력:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no] (passing이 true이면 "yes", false이면 "no" 출력)
    
    
    return 0;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨