C ++ 20 std :: common_reference의 목적은 무엇입니까?


답변:


46

common_reference 프록시 이터레이터를 수용하는 STL 이터레이터의 개념화를 생각해 내기 위해 노력했습니다.

STL과에서, 반복자는 특별한 관심의 두 가지 관련 유형이 : referencevalue_type. 전자는 반복자의 리턴 타입 operator*과는 value_type시퀀스의 요소 (const가 아닌 비 참조) 타입이다.

일반 알고리즘은 종종 다음과 같은 작업을 수행해야합니다.

value_type tmp = *it;

... 우리 는이 두 유형 사이에 어떤 관계 가 있어야한다는 것을 알고 있습니다. 비 프록시 반복자의 경우 관계는 간단합니다. reference항상 value_type이며, 선택적으로 const 및 참조 규정이 있습니다. 개념 을 정의하려는 초기의 시도InputIterator 는 표현을 *it로 변환 할 수 있어야 const value_type &하며 대부분의 흥미로운 반복자에게는 충분했습니다.

C ++ 20의 반복자가 이보다 강력 해지기를 원했습니다. 예를 들어, zip_iterator잠금 단계에서 두 시퀀스를 반복 하는의 필요성을 고려하십시오 . a의 참조를 해제 하면 두 반복자 유형 중 zip_iterator임시 유형이 표시됩니다. 따라서 a 와 a 는 다음과 같은 관련 유형을 갖습니다.pairreferencezipvector<int>vector<double>

zip반복자 reference: pair<int &, double &>
zip반복자 value_type:pair<int, double>

보시다시피,이 두 유형은 단순히 최상위 cv- 및 ref 제한을 추가하여 서로 관련이 없습니다. 그러나 두 유형을 임의로 다르게 만드는 것은 잘못된 생각입니다. 분명히 여기에는 어떤 관계가 있습니다. 그러나 관계는 무엇이며 반복자에서 작동하는 일반 알고리즘은 두 가지 유형에 대해 안전하게 가정 할 수 있습니까?

C ++ 20의 대답은 유효한 반복자 유형에 대해 프록시 유형 에 관계없이 유형 reference &&공통 참조를value_type & 공유한다는 입니다. 다시 말해서, 일부 반복자 it에는 CR다음을 올바르게 구성하는 유형 이 있습니다.

void foo(CR) // CR is the common reference for iterator I
{}

void algo( I it, iter_value_t<I> val )
{
  foo(val); // OK, lvalue to value_type convertible to CR
  foo(*it); // OK, reference convertible to CR
}

CR공통 참조입니다. 모든 알고리즘은이 유형이 존재한다는 사실에 의존 할 수 있으며 std::common_reference이를 계산하는 데 사용할 수 있습니다 .

이것이 common_referenceC ++ 20의 STL에서 수행하는 역할입니다 . 일반적으로 일반 알고리즘이나 프록시 반복자를 작성하지 않는 한 무시해도됩니다. 이터레이터가 계약자의 의무를 충족 시키도록 보장합니다.


편집 : OP도 예제를 요청했습니다. 이것은 약간 고안되었지만 C ++ 20이며 상상할 수없는 임의 액세스 범위 r의 유형 Rsort있고 범위 를 원한다고 상상해보십시오 .

또한 어떤 이유로 든과 같은 단형 비교 함수를 사용하려고한다고 상상해보십시오 std::less<T>. (범위를 타입 소거했을 수도 있고 비교 함수를 타입 삭제하고 virtual? 다시, 스트레치를 통해 전달 해야 T합니다 .) std::less<T>? 이를 위해 common_reference, 또는 그 iter_common_reference_t측면에서 구현 되는 도우미 를 사용 합니다.

using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});

범위 r에 프록시 반복자가있는 경우에도 작동 합니다.


2
어쩌면 나는 조밀하지만 zip-pair 예제에서 공통 참조가 무엇인지 명확히 할 수 있습니까?
happydave

4
이상적으로, pair<T&,U&>그리고 pair<T,U>&공통의 참조를 할 것이다, 그것은 단순히 것입니다 pair<T&,U&>. 그러나, 대한 std::pair, 아무런 변환이 없다 pair<T,U>&pair<T&,U&>이러한 변환은 원칙적으로 소리에도 불구하고가. (이것은 우연히 zipC ++ 20에서 볼 수없는 이유 입니다.)
Eric Niebler

4
@EricNiebler : " 이것은 우연히 C ++ 20에 zip 뷰가없는 이유입니다. " pair목적에 맞게 특별히 설계된 유형 대신 zip 반복자 가을 사용해야하는 이유가 있습니까? , 필요에 따라 적절한 암시 적 변환이 있습니까?
Nicol Bolas

5
@Nicol Bolas 사용할 필요가 없습니다 std::pair. 적절한 변환을 가진 적절한 쌍 유사 유형이 수행되며 range-v3은 이러한 쌍 유사 유형을 정의합니다. 위원회에서 LEWG는 표준 작업 std::pair에 단순한 std::pair작업을 하는 장단점에 대해 실사를하지 않고 표준 라이브러리에 거의 또는 전혀 그렇지 않은 유형을 표준 라이브러리에 추가하려는 아이디어를 좋아하지 않았습니다 .
Eric Niebler 19

3
tuple, pair, tomato, to- MAH- to. 및로 pair요소에 액세스 할 수있는이 멋진 기능이 있습니다 . 구조적 바인딩은 s 로 작업하는 것이 어색 하지만 일부는 아닙니다. .first.secondtuple
Eric Niebler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.