perfect forwarding

std::forward 값 범주 보존

T&& 매개변수는 호출자가 lvalue를 줬는지 rvalue를 줬는지 기억하고, std::forward<T>가 그 정보를 다음 함수 호출에 다시 적용합니다.

template<class T> void wrapper(T&& arg) process(std::forward<T>(arg));
lvalue

wrapper(lval)

T = int&

forward 결과가 lvalue 참조로 남아 process(int&)가 선택됩니다.

rvalue

wrapper(20)

T = int

임시 값의 범주가 유지되어 process(int&&) 오버로드로 전달됩니다.

xvalue

wrapper(std::move(lval))

T = int

이동 가능 표시가 유지되어 rvalue 참조 오버로드를 호출합니다.

왜 필요할까

이름 있는 arg는 lvalue

process(arg)라고 쓰면 호출자가 rvalue를 줬더라도 arg 자체는 이름이 있어 lvalue처럼 전달됩니다.

move와 구분

무조건 가져가면 std::move

forwarding wrapper에서는 보존이 목적이고, 더 이상 원본을 쓰지 않을 때만 move가 자연스럽습니다.

기억할 문장: std::forward는 완벽 전달용 조건부 캐스팅이고, std::move는 이 객체를 이동 대상으로 삼겠다는 명시적 선택입니다.