C ++ 20에서 소개 std::common_reference
합니다. 그 목적은 무엇입니까? 누군가가 그것을 사용하는 예를 줄 수 있습니까?
C ++ 20에서 소개 std::common_reference
합니다. 그 목적은 무엇입니까? 누군가가 그것을 사용하는 예를 줄 수 있습니까?
답변:
common_reference
프록시 이터레이터를 수용하는 STL 이터레이터의 개념화를 생각해 내기 위해 노력했습니다.
STL과에서, 반복자는 특별한 관심의 두 가지 관련 유형이 : reference
와 value_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 는 다음과 같은 관련 유형을 갖습니다.pair
reference
zip
vector<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_reference
C ++ 20의 STL에서 수행하는 역할입니다 . 일반적으로 일반 알고리즘이나 프록시 반복자를 작성하지 않는 한 무시해도됩니다. 이터레이터가 계약자의 의무를 충족 시키도록 보장합니다.
편집 : OP도 예제를 요청했습니다. 이것은 약간 고안되었지만 C ++ 20이며 상상할 수없는 임의 액세스 범위 r
의 유형 R
이 sort
있고 범위 를 원한다고 상상해보십시오 .
또한 어떤 이유로 든과 같은 단형 비교 함수를 사용하려고한다고 상상해보십시오 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
에 프록시 반복자가있는 경우에도 작동 합니다.
pair<T&,U&>
그리고 pair<T,U>&
공통의 참조를 할 것이다, 그것은 단순히 것입니다 pair<T&,U&>
. 그러나, 대한 std::pair
, 아무런 변환이 없다 pair<T,U>&
에 pair<T&,U&>
이러한 변환은 원칙적으로 소리에도 불구하고가. (이것은 우연히 zip
C ++ 20에서 볼 수없는 이유 입니다.)
pair
목적에 맞게 특별히 설계된 유형 대신 zip 반복자 가을 사용해야하는 이유가 있습니까? , 필요에 따라 적절한 암시 적 변환이 있습니까?
std::pair
. 적절한 변환을 가진 적절한 쌍 유사 유형이 수행되며 range-v3은 이러한 쌍 유사 유형을 정의합니다. 위원회에서 LEWG는 표준 작업 std::pair
에 단순한 std::pair
작업을 하는 장단점에 대해 실사를하지 않고 표준 라이브러리에 거의 또는 전혀 그렇지 않은 유형을 표준 라이브러리에 추가하려는 아이디어를 좋아하지 않았습니다 .
tuple
, pair
, tomato
, to
- MAH
- to
. 및로 pair
요소에 액세스 할 수있는이 멋진 기능이 있습니다 . 구조적 바인딩은 s 로 작업하는 것이 어색 하지만 일부는 아닙니다. .first
.second
tuple