C++ 초급 - 12. 최신 C++ 기능 소개 (3 - C++17: 구조적 바인딩과 if constexpr)

2025. 2. 22. 18:12프로그래밍 언어/C++

📌 12.3 C++17: 구조적 바인딩과 if constexpr

C++17에서는 코드를 더욱 간결하고 직관적으로 작성할 수 있도록 하는 기능이 추가되었다.
대표적으로 "구조적 바인딩(structured bindings)""if constexpr"이 있다.
이 기능들은 코드의 가독성을 높이고, 실행 속도를 최적화하는 데 유용하다.


📌 1. 구조적 바인딩 (Structured Bindings)을 활용한 변수 분해

C++17 이전에는 튜플(tuple)이나 std::pair 같은 복합 데이터를 개별 변수로 분해하려면 std::get<> 또는 std::tie()를 사용해야 했다.
하지만 C++17에서는 "구조적 바인딩"을 도입하여 더 직관적인 방식으로 변수에 값을 분해 가능하다.

🔹 (1) 기존 방식 (std::get<>, std::tie())

💡 예제: C++14에서 std::tuple 분해

#include <iostream>
#include <tuple>

int main() {
    std::tuple<int, double, std::string> t(1, 3.14, "C++");

    int a;
    double b;
    std::string c;

    std::tie(a, b, c) = t;  // 기존 방식 (C++14)

    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
    return 0;
}

🔹 출력 결과

a: 1, b: 3.14, c: C++

🔹 문제점

  • 변수를 미리 선언해야 함.
  • std::tie()를 사용해야 하며, 직관적이지 않음.

🔹 (2) C++17 구조적 바인딩 활용

C++17에서는 구조적 바인딩을 활용하여 더 간결한 방식으로 변수 분해 가능.

💡 예제: C++17 구조적 바인딩을 사용한 std::tuple 분해

#include <iostream>
#include <tuple>

int main() {
    std::tuple<int, double, std::string> t(1, 3.14, "C++");

    auto [a, b, c] = t;  // 구조적 바인딩 (C++17)

    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
    return 0;
}

🔹 출력 결과

a: 1, b: 3.14, c: C++

💡 설명

  • 변수를 미리 선언할 필요 없이 한 줄로 데이터 분해 가능.
  • 더 간결하고 직관적인 문법 제공.

🔹 (3) std::pair, std::array에서도 활용 가능

💡 예제: std::pair에 구조적 바인딩 적용

#include <iostream>
#include <utility>

int main() {
    std::pair<int, std::string> p = {10, "Hello"};

    auto [num, text] = p;  // 구조적 바인딩

    std::cout << "num: " << num << ", text: " << text << std::endl;
    return 0;
}

🔹 출력 결과

num: 10, text: Hello

💡 예제: std::array 활용

#include <iostream>
#include <array>

int main() {
    std::array<int, 3> arr = {1, 2, 3};

    auto [x, y, z] = arr;  // 구조적 바인딩 사용

    std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl;
    return 0;
}

🔹 출력 결과

x: 1, y: 2, z: 3

📌 2. if constexpr을 활용한 컴파일 타임 최적화

🔹 (1) 기존 문제점 (런타임 조건문)

C++17 이전에는 템플릿 내부에서 조건문을 사용할 경우 모든 코드가 컴파일되어 런타임에서 실행되었음.
이로 인해 불필요한 코드가 실행될 수도 있으며, 최적화가 어려움.

💡 예제: C++14에서 if 사용 (불필요한 연산 수행 가능성)

#include <iostream>

template <typename T>
void printType(T value) {
    if (std::is_integral<T>::value) {  // 정수 타입인지 확인
        std::cout << "정수형 데이터: " << value << std::endl;
    } else {
        std::cout << "일반 데이터: " << value << std::endl;
    }
}

int main() {
    printType(10);     // 정수형 데이터
    printType(3.14);   // 일반 데이터

    return 0;
}

🔹 문제점

  • 일반적인 if 문은 런타임에서 조건을 평가.
  • 컴파일러가 불필요한 연산을 제거하지 못함.

🔹 (2) C++17 if constexpr을 활용한 최적화

C++17에서는 컴파일 타임에 조건을 평가하여 불필요한 코드가 컴파일되지 않도록 할 수 있음.
💡 예제: if constexpr을 활용한 최적화

#include <iostream>
#include <type_traits>

template <typename T>
void printType(T value) {
    if constexpr (std::is_integral_v<T>) {  // 컴파일 타임에서 정수형 여부 판별
        std::cout << "정수형 데이터: " << value << std::endl;
    } else {
        std::cout << "일반 데이터: " << value << std::endl;
    }
}

int main() {
    printType(10);     // 정수형 데이터
    printType(3.14);   // 일반 데이터

    return 0;
}

🔹 출력 결과

정수형 데이터: 10
일반 데이터: 3.14

💡 설명

  • if constexpr을 사용하면 std::is_integral_v<T>가 true일 경우 else 부분이 컴파일되지 않음.
  • 불필요한 코드가 제거되어 최적화됨.

📌 3. 기본적인 문법 변화 및 코드 단순화

C++17에서는 구조적 바인딩과 if constexpr 외에도 다양한 문법 개선이 이루어졌다.

🔹 (1) constexpr을 활용한 컴파일 타임 연산

  • C++17에서는 constexpr 함수 내에서 if 문과 반복문(for, while)을 사용할 수 있음.
  • 이를 통해 더 강력한 컴파일 타임 계산이 가능.

💡 예제: constexpr을 활용한 컴파일 타임 연산

#include <iostream>

constexpr int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

int main() {
    constexpr int result = factorial(5);  // 컴파일 타임에 계산됨
    std::cout << "5! = " << result << std::endl;
    return 0;
}

🔹 출력 결과

5! = 120

💡 설명

  • C++14까지는 constexpr 함수에서 if 문을 사용할 수 없었으나, C++17에서는 가능.
  • 컴파일 타임에서 계산이 이루어져 런타임 성능 최적화.

📌 4. 정리

개념  설명
구조적 바인딩 std::tuple, std::pair, std::array 등의 데이터를 직관적으로 분해 가능
if constexpr 컴파일 타임 조건문을 사용하여 불필요한 코드 제거 및 최적화
코드 단순화 constexpr 함수에서 if 문 사용 가능