본문 바로가기
프로그래밍/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

 

 

 

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: 다양한 형태의 호출 가능한 객체를 일반적인 방식으로 보관하고 호출할 수 있게 도와주는 템플릿 클래스입니다.

 

 

댓글