본문 바로가기
프로그래밍/C++

C++11 주요 업데이트 : std::tuple, Variadic Templates, std::bind, std::function

by 머니테크리더 2023. 10. 3.
반응형

C++11 주요 업데이트 : std::tuple, Variadic Templates, std::bind, std::function
C++11 주요 업데이트 : std::tuple, Variadic Templates, std::bind, std::function

 

🔖 INDEX

     

     

    std::tuple

    튜플(std::tuple)은 C++11에서 도입된 컨테이너 유형으로, 서로 다른 타입의 여러 원소를 하나의 단위로 묶을 수 있습니다. 이는 함수에서 여러 값을 반환하거나, 여러 값을 단일 객체로 묶어 전달할 때 유용합니다.

     

    주요 특징

    • 다양한 타입의 값: 튜플은 서로 다른 타입의 여러 원소를 저장할 수 있습니다.
    • 고정 크기: 튜플의 크기는 생성 시에 결정되며, 나중에 변경할 수 없습니다.
    • 값 접근: std::get<index>(tuple) 함수나 구조화된 바인딩을 사용하여 튜플의 원소에 접근할 수 있습니다.

     

    사용 예제

    튜플 생성 및 값 할당

    #include <tuple>
    
    int main() {
        std::tuple<int, double, std::string> t1(1, 3.14, "Hello");
        auto t2 = std::make_tuple(2, 2.71, "World");
    }

     

    값 접근

    int value = std::get<0>(t1);  // 1을 반환
    std::string str = std::get<2>(t1);  // "Hello"를 반환

     

    여러 값 반환

    std::tuple<int, double> func() {
        return std::make_tuple(1, 3.14);
    }
    
    int main() {
        auto [val, pi] = func();  // C++17의 구조화된 바인딩을 사용
    }

     

    튜플 비교

    튜플은 기본적인 비교 연산을 지원합니다. 첫 번째 원소부터 순서대로 비교됩니다.

    if (t1 < t2) { /* ... */ }

     

    주요 함수

    • std::make_tuple(...): 값들을 받아 튜플을 생성합니다.
    • std::get<index>(tuple): 지정된 인덱스의 원소에 접근합니다.
    • std::tie(...): 튜플의 원소들을 변수에 바인딩합니다.

     

    주요 이점

    • 타입 유연성: 튜플을 사용하면 다양한 데이터 타입을 하나의 컨테이너에 저장할 수 있습니다. 이는 서로 다른 타입의 정보를 묶어 관리하고 전달할 때 유용합니다.
    • 복수 반환 값: 여러 값을 한 번에 반환할 필요가 있을 때, 튜플은 이를 간결하게 해결할 수 있습니다. 예를 들어, 함수에서 두 개 이상의 결과 값을 반환하고 싶을 때 튜플을 활용할 수 있습니다.
    • 구조화된 바인딩: C++17부터, 튜플의 값을 여러 변수에 한 번에 분배할 수 있는 구조화된 바인딩을 사용할 수 있습니다. 이를 통해 코드의 가독성과 편의성이 크게 향상됩니다.
    • 표준 라이브러리와의 통합: std::tuple은 C++ 표준 라이브러리의 일부로 제공되므로, 다른 표준 라이브러리 기능과 잘 통합됩니다. 예를 들어, std::pair와 유사하게 사용되거나, 알고리즘에 유용하게 사용될 수 있습니다.
    • 비교 연산: 튜플은 기본적인 비교 연산을 지원합니다. 첫 번째 원소부터 순서대로 비교되므로, 원소 간의 상대적 순서를 기반으로 튜플 전체를 쉽게 비교할 수 있습니다.
    • 런타임에 크기나 타입 변경 불가: 튜플의 크기나 타입은 컴파일 시간에 결정되므로, 예기치 않은 변경이나 오류를 방지할 수 있습니다.
    • 메모리 효율: 튜플은 메모리 할당 없이 연속적인 메모리 공간에 값을 저장하기 때문에, 동적 메모리 할당의 오버헤드나 프래그먼테이션 문제 없이 효율적으로 메모리를 사용합니다.

     

     

    Variadic Templates

    C++11에서 도입된 가변 인자 템플릿(Variadic Templates)은 함수나 클래스가 가변 수의 템플릿 인자를 받아들일 수 있게 해주는 기능입니다. 이를 사용하여 다양한 타입의 인자들을 처리하는 템플릿 함수나 클래스를 작성할 수 있습니다.

     

    기본 구문

    '...' (ellipsis)를 사용하여 가변 인자 템플릿을 선언합니다.

    template<typename... Args>
    void functionName(Args... args);

     

    사용 예제

    가변 인자를 받는 함수 정의

    template<typename... Args>
    void printValues(Args... args) {
        // ...
    }

     

    Parameter Pack

    가변 인자는 'parameter pack'이라는 형태로 취급됩니다. args...와 같이 ellipsis를 사용하여 parameter pack의 내용을 처리할 수 있습니다.

    template<typename T>
    void printSingleValue(T value) {
        std::cout << value << " ";
    }
    
    template<typename... Args>
    void printValues(Args... args) {
        (printSingleValue(args), ...);  // C++17 fold expression
    }
    
    int main() {
        printValues(1, 2.0, "Hello", 'A');
    }

    위 예제에서 printValues 함수는 다양한 타입과 수의 인자를 받아들일 수 있습니다. C++17의 fold expression을 사용하여 모든 인자에 대해 printSingleValue 함수를 호출합니다.

     

    클래스 템플릿에서의 활용

    가변 인자 템플릿은 클래스 템플릿에서도 사용할 수 있습니다. 예를 들어, std::tuple은 가변 인자 템플릿을 활용한 대표적인 클래스입니다.

     

    주의 사항

    • 가변 인자 템플릿은 다루기 까다롭기 때문에 사용 시 주의가 필요합니다. 특히 재귀적 템플릿 패턴을 사용하여 parameter pack을 처리할 때는 종료 조건을 잘 설정해야 합니다.
    • C++17의 fold expression을 활용하면 가변 인자 템플릿의 처리가 훨씬 간결하고 직관적이게 됩니다.

     

     

    std::bind와 std::function

    C++11에서는 함수와 관련된 다양한 객체를 쉽게 다룰 수 있게 도와주는 유틸리티와 클래스를 도입하였습니다. 그 중 std::bind와 std::function은 함수 호출을 더 유연하고 일반적인 방식으로 다룰 수 있게 도와줍니다.

     

    std::bind

    std::bind는 함수나 함수 객체, 멤버 함수 포인터 등을 받아 고정된 인자나 조건을 적용한 새로운 호출 가능한 객체를 반환합니다.

     

    기본 구문

    auto bound_function = std::bind(function_name, arg1, arg2, ...);

     

    사용 예제

    #include <iostream>
    #include <functional>
    
    void printSum(int a, int b) {
        std::cout << a + b << std::endl;
    }
    
    int main() {
        auto boundPrintSum = std::bind(printSum, 5, 10);
        boundPrintSum();  // 출력: 15
    }

     

    std::bind에는 _1, _2, ... 등의 placeholder도 사용할 수 있어, 바인딩시에 아직 정해지지 않은 인자를 전달받을 수 있습니다.

    auto boundPrintWithPlaceholder = std::bind(printSum, 5, std::placeholders::_1);
    boundPrintWithPlaceholder(10);  // 출력: 15

     

    std::function

    std::function은 호출 가능한 객체를 보관하고 호출하는 일반적인 인터페이스를 제공하는 템플릿 클래스입니다. 함수 포인터, 람다, 멤버 함수 포인터, std::bind로 생성된 객체 등 여러 형태의 호출 가능한 객체를 보관할 수 있습니다.

     

    기본 구문

    std::function<return_type(arg_types...)> functionName;

     

    사용 예제

    #include <iostream>
    #include <functional>
    
    void sayHello() {
        std::cout << "Hello!" << std::endl;
    }
    
    int main() {
        std::function<void()> func = sayHello;
        func();  // 출력: Hello!
    
        // 람다 함수와 함께 사용
        func = []() { std::cout << "Hello from lambda!" << std::endl; };
        func();  // 출력: Hello from lambda!
    }

     

    요약

    • std::bind: 다양한 함수나 호출 가능한 객체에 대해 인자를 고정하거나 재배치하여 새로운 호출 가능한 객체를 생성합니다.
    • std::function: 다양한 형태의 호출 가능한 객체를 일반적인 방식으로 보관하고 호출할 수 있게 도와주는 템플릿 클래스입니다.

     

     

    댓글