임시 파이프를 범위 작업으로 되돌릴 수 있습니까?


9

(특히 is ) generate_my_range를 모델링 하는 클래스가 있다고 가정하십시오 . 그런 다음 다음 코드가 맞습니다.rangeregular

auto generate_my_range(int some_param) {    
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op);
}
auto cells = generate_my_range(10) | ranges::to<std::vector>;

가요 my_custom_rng_gen(some_param)I는두고 일단 (제 1) 파이프 조작자 취한 값, 또는 I가 매달려 참조가 수행 generate_my_range범위?

기능 호출과 동일 ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)합니까?

lvalue 참조를 사용하면 정확합니까? 예 :

auto generate_my_range(int some_param) {
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  auto tmp_ref = my_custom_rng_gen(some_param);
  return tmp_ref | ranges::views::transform(my_transform_op);
}

이러한 작업의 값으로 범위를 가져 가면 lvalue 참조를 컨테이너에 전달하면 어떻게해야합니까? ranges::views::all(my_container)패턴을 사용해야합니까 ?


my_custom_rng_gen (some_param)이 이미 바인딩되어 있습니까? take (5)없이 godbolt.org/z/aTF8RN 같은 것을 의미 합니까?
Porsche9II

@ Porsche9II 네, 이것은 한정된 범위입니다. 컨테이너라고 가정 해 봅시다
Bérenger

답변:


4

범위 라이브러리에는 두 가지 종류의 작업이 있습니다.

  • 전망 게으른과 존재하는 기본 용기가 필요합니다.
  • 열망하고 결과적으로 새로운 컨테이너를 생산하는 조치 (또는 기존 컨테이너를 수정)

보기는 가볍습니다. 값을 기준으로 전달하고 기본 컨테이너가 유효하고 변경되지 않은 상태로 유지되도록 요구합니다.

로부터 범위-V3 문서

뷰는 기본 요소 시퀀스를 변경하거나 복사하지 않고 사용자 정의 방식으로 표시하는 경량 래퍼입니다. 뷰는 작성 및 복사가 저렴하며 소유하지 않은 참조 의미가 있습니다.

과:

기본 범위에서 반복자 또는 센티넬을 무효화하는 작업은 해당 범위의 모든 부분을 참조하는 모든 뷰도 무효화합니다.

기본 컨테이너가 손상되면 모든 반복자가 무효화됩니다.

코드에서 를 구체적으로 사용하고 있습니다 ranges::views::transform. 파이프는 구문 그대로 설탕으로 그대로 작성하기가 쉽습니다. 파이프의 마지막 부분을보고 생산물을 확인해야합니다. 귀하의 경우에는보기입니다.

파이프 연산자가 없으면 다음과 같이 보일 것입니다.

ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)

그런 식으로 여러 변환이 연결되어 있으면 얼마나 추악한 지 알 수 있습니다.

따라서 my_custom_rng_gen어떤 종류의 컨테이너를 생성하면 변환 한 다음 반환하면 해당 컨테이너가 파괴되고 뷰에서 매달려있는 참조가 있습니다. 경우 my_custom_rng_gen이 범위 바깥의 삶, 모든 것이 괜찮하는 컨테이너에 다른보기이다.

그러나 컴파일러는 임시 컨테이너에 뷰를 적용하고 있음을 인식하고 컴파일 오류를 표시합니다.

함수가 범위를 컨테이너로 반환하도록하려면 결과를 명시 적으로 "구체화"해야합니다. 이를 위해 ranges::to함수 내에서 연산자를 사용하십시오 .


업데이트 : 귀하의 의견에 대해 더 유쾌하게하기 위해 "문서는 범위 / 배관 구성이 뷰를 취하고 저장한다고 어디에 표시합니까?"

파이프는 읽기 쉬운 표현으로 사물을 연결하는 구문 설탕 일뿐입니다. 사용 방법에 따라보기를 반환하거나 반환하지 않을 수 있습니다. 오른쪽 인수에 따라 다릅니다. 귀하의 경우 :

`<some range> | ranges::views::transform(...)`

따라서 표현식은 모든 views::transform리턴을 리턴합니다.

이제 변환의 문서를 읽음으로써 :

아래는 Range-v3가 제공하는 게으른 범위 조합기 또는 뷰의 목록과 각각의 사용법에 대한 설명입니다.

[...]

views::transform

소스 범위와 단항 함수가 주어지면 각 결과 요소가 단항 함수를 소스 요소에 적용한 결과 인 새 범위를 리턴하십시오.

따라서 범위를 반환하지만 지연 연산자이므로 반환되는 범위 모든 의미를 가진 뷰입니다.


확인. 나에게 조금 신비한 것은 컨테이너를 파이프에 전달할 때 어떻게 작동합니까 (예 : 컴포지션으로 만든 범위 객체). 어떻게 든 컨테이너의 뷰를 저장해야합니다. 완료 ranges::views::all(my_container)되었습니까? 뷰가 파이프로 전달되면 어떻게 될까요? 컨테이너 또는 뷰가 전달되었음을 인식합니까? 필요합니까? 어떻게?
Bérenger

"컴파일러는 임시 컨테이너에 뷰를 적용하고 컴파일 오류가 발생했다는 것을 인식 할 수 있어야합니다."저도 그렇게 생각했습니다. 값)이 충족되지 않습니다. 그런 것들은 range-v3에 의해 수행됩니다. 그러나이 경우에는 아무런 문제가 없습니다. 컴파일하고 실행합니다. 따라서 정의되지 않은 동작이있을 수 있지만 표시되지 않습니다.
Bérenger

실수로 코드가 올바르게 실행되는지 또는 모든 것이 올바르게 작동하는지 확인하려면의 내용을 확인해야합니다 my_custom_rng_gen. 파이프와 transform후드 아래에서 정확히 상호 작용 하는 방법 은 중요하지 않습니다. 전체 표현식은 범위를 인수 (컨테이너 또는 일부 컨테이너에 대한보기)로 사용하여 해당 컨테이너에 다른보기를 리턴합니다. 반환 값은 컨테이너이므로 뷰를 소유하지 않습니다.
CygnusX1

1

ranges-v3 문서 에서 가져 왔습니다 .

뷰 [...]에는 비 소유 참조 시맨틱이 있습니다.

단일 범위 객체를 사용하면 파이프 라인 작업이 가능합니다. 파이프 라인에서, 어떤 방식으로 범위가 느리게 조정되거나 간헐적으로 돌연변이되고, 결과는 추가의 적응 또는 돌연변이에 즉시 이용 가능하다. 게으른 적응은 견해에 의해 처리되고, 열성적인 돌연변이는 행동에 의해 처리됩니다.

// taken directly from the the ranges documentation
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::remove_if([](int i){ return i % 2 == 1; })
              | views::transform([](int i){ return std::to_string(i); });
// rng == {"2","4","6","8","10"};

위의 코드에서 rng는 단순히 기본 데이터에 대한 참조와 필터 및 변환 함수를 저장합니다. rng가 반복 될 때까지 작업이 수행되지 않습니다.

임시 범위는 컨테이너로 생각할 수 있다고 말 했으므로 함수는 매달려있는 참조를 반환합니다.

다시 말해, 기본 범위가보기보다 오래 지속되거나 문제가 발생했는지 확인해야합니다.


예, 뷰는 비 소유이지만 문서에서 범위 / 배관 구성시 뷰를 가져 와서 저장하는 위치는 어디입니까? 범위가 rvalue 참조로 제공되는 경우 값으로 저장하면 다음과 같은 정책을 가질 수 있습니다 (좋은 생각).
Bérenger

1
@ Bérenger 나는 범위 문서에서 조금 더 추가했습니다. 그러나 요점은 실제로 다음과 같습니다. 뷰가 비 소유 입니다. rvalue를 건네주는 것은 중요하지 않습니다.
Rumburak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.