티스토리 뷰

 오른값 참조를 사용할 때, 우리는 &&를 뒤에 붙여 오른값 참조임을 명시한다. 하지만 보편 참조의 경우에도 &&를 붙이기 때문에 구분해서 사용해야만 한다. 예시를 살펴보자.

void f(Widget&& param);           // 오른값 참조

Widget&& var1 = Widget();         // 오른값 참조

auto&& var2 = var1;               // 오른값 참조 아님

template<typename T>
void f(std::vector<T>&& param);   // 오른값 참조

template<typename T>
void f(T&& param);                // 오른값 참조 아님

 언뜻보기에는 오른값 참조처럼 보이지만 보편 참조인 경우가 상당히 많다. 보편 참조의 의미는 오른값 참조이거나 왼값 참조 중 하나라는 의미이다. 보편 참조는 일반적으로 두 가지 문맥에서 나타난다. 하나는 template 을 사용하는 경우이고 나머지 하나는 auto 를 사용하는 경우이다. 두가지 모두 형식 연역이 일어난다는 공통점이 있다. 하지만 몇가지 주의할 점이 있다. 형식 연역이 일어나도 보편 참조가 아닌 경우가 있다. 예를들어 살펴보자.

const를 사용하는 경우

template<typename T>
void f(const T&& param);   // 오른값 참조

직접적인 형식 연역이 아닌 경우

template<typename T>
void f(std::vector<T>&& param); // 오른값 참조

템플릿 안에서 형식 연역이 일어나지 않는 경우

template<class T, class Allocator = allocator<T>>
class vector {
public:
    void push_back(T&& x);
    ...
};

push_back 함수는 보편 참조를 요구하는 형태이지만 실제로는 형식 연역이 일어나지 않는다. push_back 은 반드시 구체적으로 인스턴스화 된 vector 의 일부이어야 하며, 그 인스턴스의 형식은 push_back 의 선언을 완전하게 결정하기 때문이다.

std::vector<Widget> v;

class vector<Widget, allocator<Widget>> {
public:
    void push_back(Widget&& x):
    ...
};

 v 를 선언하게 되면 std::vector 의 코드는 인스턴스화된다. push_back 함수는 이제 형식 연역이 일어나지 않기 때문에 오른값 참조임이 명백하다. push_back 과 비슷한 emplace_back 함수는 형식 연역이 일어난다. 형식 연역이 일어나므로 emplace_back 의 경우에는 보편 참조이다.

template<class T, class Allocator = allocator<T>>
class vector {
public:
    template<class... Args>
    void emplace_back(Args&&... args);
    ...
};

 

 

참고 서적

스콧 마이어스, Effective Modern C++

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함