2012-01-13 6 views
4

편집 : 내가 물어 보는 가장 일반적인 사용 사례는 std::forward_as_tuple()에서 rvalue-references의 튜플을받는 함수를 만들 때입니다.std :: forward_as_tuple() 결과를 해당 객체의 rvalue-reference 멤버에서 이동할 수있는 여러 함수에 전달합니까?

나는 그들이 내가 조언을 열려있어 (를 rvalue 참조가 있다면 생성자 초기화에 전달 된 객체의이 볼 수있는 회원을 확인했기 때문에이 질문이 마음에 온 이유는 나를 말하는 것은이 잘못 잘못 잘못이다 ... 장래에 이것을 피하기위한 경험 법칙을 따라하기를 바랍니다. 약간 다른 맥락에서, 나는 rvalue-reference 멤버를 가진 객체를 여러 멤버 함수 (또는 함수 객체)에 넘겨 줄지도 모릅니다. 내가 제어 할 수도 있고 제어하지 않을 수도 있고, 멤버들로부터 이동할 수도 있습니다.

template<typename... Args> 
void my_func(std::tuple<Args...>&& tup) { 

    //if tup's members are rvalue references, 
    //and this function moves guts from tup members, then... 
    func_i_dont_control(tup); 

    //what happens here if moves are done on the same members? 
    another_func_i_dont_control(std::move(tup)); 
} 

나는를 rvalue 참조 회원의 다른 논의와 함께, Use of rvalue reference members?을 검토 한 결과,하지만 난 확실히이 밖으로 정렬하는 것은 매우 수 아니에요.

나는 무엇이 일어날지를 묻는 것뿐만 아니라,이 시나리오가 전혀 일어나지 않아야하는지, 그리고 rvalue-reference 멤버를 포함하는 객체를 지나갈 때 염두에 두어야 할 핵심 규칙을 물어볼 것입니다.

+1

예제에서'tup'을 포기하지 않아야합니까? –

+0

흠, tup 자체가 템플릿 인수가 아닐지라도 나는 여전히 그렇게하겠습니까? 나는 완벽한 포워딩에서 여전히 약간 녹색이다. –

+0

함수 템플릿 매개 변수로 불완전한 형식이 있으면 전달하십시오. –

답변

1

이 코드 func_i_dont_control에서 매개 변수를 자동으로 도용 할 수 없습니다. rvalues ​​만 rvalue 참조에 바인딩되고 명명 된 변수는 rvalue가 아닙니다. 코드가 컴파일되지 않거나 func_i_dont_control (과부하가 있음)에서 이동 의미를 사용하지 않습니다.

func_i_dont_control에 튜플을 훔칠 기회를 부여하려면 (튜플을 기준점에 바인딩하는 경우) std::move(tup)으로 명시 적으로 rvalue로 캐스팅해야합니다.

(그것에서 움직이지해야 좌변 참조를 복용하는 기능, 그렇지 않으면 우리가 정말 무슨 일이 일어날 지 알 수 없습니다.)


편집하지만 문제는 대한 될 것 같지 않습니다 튜플 자체는 멤버이지만 다시 말하지만, 그 구성원은 rvalues되지 않습니다, 그래서 func_i_dont_control 명시 적으로 그들을 이동해야합니다. 나는 그것이 당신의 기능에서 일어나지 않는 rvalue로서 전체 튜플을받지 않는다면 그렇게하는 것이 "도덕적 권리"*라고 생각하지 않습니다.

* 이동 의미론을 사용하면 특정 지침을 따라야합니다.근본적으로 당신은 rvalue에 무엇이든 던져 넣을 수 있고 그것으로부터 이동할 수 있습니다. lvalue 또는 rvalue references를 다루는 것이 중요하지 않습니다. 이 가이드 라인을 따르면 이동 의미론이 올바르게 작동합니다. 만약 당신이 그 가이드 라인을 무시한 값으로 캐스팅을 시작하면 함수 호출 후에 객체가 사라지기 시작합니다.

+0

그래서 rvalue-reference 멤버를 매개 변수로 사용하여 개체를 전달하면 (이름 지정) 개체의 멤버가 변경됩니까? 'std :: forward_as_tuple()'이 그 결과를 가져 와서 객체의 이름을 지정하는 함수에 건네면 어떻게 될까요? 나는 곤란하지 않으려 고 노력하고있어, 내 머리가 그냥 못 박는 것을 시도하고있다. 롤. –

+0

그러나 공식적으로 이것은 'func_i_dont_control'을 사용하지 않고도 일을 망칠 수 있습니다. 원칙적으로'func_i_dont_control'는 나중의 사용을 위해 인수에 대한 포인터를 저장할 수 있습니다.이 포인터는 나중에 이동 된 객체를 가리 킵니다. 그러나 나는 그 자체로 나쁜 스타일이 될 것이라고 생각한다. (특히 그 행동을 눈에 띄지 않게 문서화하지 않는 것은 좋지 않은 스타일이다. 문서를 남겨두면, 그 함수를 rvalue 참조 인수). – celtschk

1

튜플과 가변 인자 템플릿의 사용은 문제의 지점에서 떨어지다 것 같다 그래서 내가 그것을 바꿔 보자

void func(std::unique_ptr<Foo>&& foo) { 
    std::unique_ptr<Foo> bar1(std::move(foo)); 
    std::unique_ptr<Foo> bar2(std::move(foo)); 
} 

은 무엇 여기됩니까? 음, bar2에는 항상 null 포인터가 포함되어 있습니다 (원래 값 foo에 따라 bar1이 될 수 있음). 이동 생성자는 안전상의 이유로 정확하게 사용할 수있는 상태에 표창장은 필요로을 대상 남겨 두어야하기 때문에

는 더 정의되지 않은 동작 없습니다. 따라서 에서 옮긴 개체를 사용할 수는 있지만 그 상태는별로 흥미롭지 않습니다. 기본 구성된 상태와 동등 할 필요는 없습니다. 단지 오래된 상태 일 수 있습니다.

+1

이 예제는'std :: move (foo)'없이 컴파일되지 않습니다. – visitor

+0

@visitor : oups, 잡기 주셔서 감사합니다 :) –

+0

개체를 사용 가능한 상태로 두는 것에 대해 언급 할 때, 나는 정말로 긴 기사 r 가치 참고 및 완벽한 포워딩을 다루고 있습니다. [이 페이지] (http://thbecker.net/articles/rvalue_references/section_04.html)의 하단 단락을 참조하십시오. –