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

C++] perfect forwarding 이란?(완벽 전달자)

by Hwan2 2020. 8. 31.
728x90
반응형

C++에는 템플릿이라는 항목이 있습니다.

 

템플릿은 타입을 정하지 않은 것으로 코드에 유연성을 제공하게 됩니다.

 

대표적으로 템플릿이 있는걸 접할 수 있는 라이브러리는 STL의 vector, map, queue 등이 있습니다.

 

이 템플릿엔 특이한점이 있는데 std::forward<T>가 있다는 것입니다.

 

우선 템플릿에 대한 기본적인 설명을 해보겠습니다.

 

 

기본적인 template 함수

#include <iostream>

template<class T>
void fnc(T n) {
    std::cout << typeid(n).name() << " : " << n << std::endl;
}

int main() {
    int n = 10;
    fnc(n);
    fnc("hwan");
    fnc(1.123);
    
    return 1;
}

 

 

이렇게 템플릿을 선언하게 된다면 데이터 타입에 유연성을 함수에 제공할 수 있게 됩니다.

 

하지만 이러한 템플릿 함수에 참조자(l-value)나 r-value를 넘겨줄 수도 있습니다.

 

 

참조자(l-value) template 함수

#include <iostream>

template<class T>
void fnc(T& n) {    //lvalue 참조로 받음.
    std::cout << typeid(n).name() << " : " << n << std::endl;
}

int main() {

    int n = 10;
    fnc(n);       //OK
    fnc("hwan");  //OK
    fnc(1.123);   //error
    
    return 1;
}

 

fnc 함수는 lvalue 참조(T&)를 매개변수로 사용합니다.

 

변수 n과 문자열 리터럴 "hwan"은 둘 다 lvalue입니다.

 

리터럴 1.123은 rvalue이며, lvalue 참조에 바인딩할 수 없습니다.

 

forward reference 함수(std::forward<T&&>)

#include <iostream>

template<class T>
void fnc(T&& n) {   //forward reference
    std::cout << typeid(n).name() << " : " << n << std::endl;
}

int main() {
    int n = 10;
    fnc(n);       //OK
    fnc("hwan");  //OK
    fnc(1.123);   //OK
    
    return 1;
}

 

보통 &&는 rvalue 참조를 나타내며, 이를 사용하여 데이터를 move할 수 있습니다.

그러나 템플릿에서 T&& 형태로 사용될 때, 이는 "forwarding reference"(또는 "universal reference")라고 하며, lvalue와 rvalue 모두를 받을 수 있습니다.

 

이를 통해 템플릿 함수는 인자를 그 원래의 값 카테고리(lvalue 또는 rvalue)로 다른 함수에 전달할 수 있게 됩니다.

이때 std::forward<T> 함수가 중요한 역할을 합니다. 

 

std::forward<T>는 함수에 전달된 인자를 변경 없이 그대로 다른 함수에 전달하도록 도와줍니다.

즉, std::forward<T>를 사용하면 lvalue는 lvalue로, rvalue는 rvalue로 다시 전달할 수 있습니다.

 

이러한 방식으로, 탬플릿 함수는 "perfect forwarding"을 구현할 수 있으며, 이는 인자가 원래 가지고 있던 값 카테고리를 보존하는데 도움이 됩니다.

 

마무리 코드

#include <iostream>

template<class T>
void print(T& n) {
    std::cout << "l-value" << std::endl;
}

template<class T>
void print(T&& n) {
    std::cout << "r-value" << std::endl;
}

template<class T>
void fnc(T&& n) {
    print(std::forward<T>(n));
}

int main() {
    int n = 10;
    fnc(n);
    fnc("hwan");
    fnc(1.123);
    
    return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

댓글


스킨편집 -> html 편집에서