C ++ 20 std :: common_referenceの目的は何ですか?


回答:


46

common_reference プロキシイテレータに対応するSTLのイテレータの概念化を思い付いた私の努力から生まれました。

STLでは、反復子には2つのタイプの関連する特別な関心がreferenceありvalue_typeます。およびです。前者はイテレータのの戻り値の型でoperator*あり、value_typeはシーケンスの要素の(非const、非参照)型です。

一般的なアルゴリズムでは、多くの場合、次のようなことを行う必要があります。

value_type tmp = *it;

...したがって、これら2つのタイプの間には何らかの関係があるはずです。非プロキシイテレータの場合、関係は単純referenceです。常にでvalue_type、オプションでconstと参照が修飾されています。概念を定義するための初期の試みでInputIteratorは、式*itがに変換可能であることが必要であり、const value_type &興味深い興味深い反復子にはそれで十分です。

C ++ 20のイテレータをこれよりも強力にしたかったのです。たとえばzip_iterator、ロックステップで2つのシーケンスを反復するの必要性を検討してください。を間接参照すると、2つのイテレータの型のzip_iterator一時的なものを取得します。したがって、a とaには、次のタイプが関連付けられます。pairreferencezipvector<int>vector<double>

zipイテレータのreferencepair<int &, double &>
zipイテレータのvalue_typepair<int, double>

ご覧のとおり、これらの2つのタイプは、トップレベルのcv-およびref修飾を追加するだけでは互いに関連していません。しかし、2つのタイプを任意に異なるものにすると、間違っているように感じます。明らかに、ここには何らかの関係があります。しかし、その関係は何であり、イテレータで動作する一般的なアルゴリズムは2つのタイプについて何を安全に想定できるでしょうか。

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タイプのランダムアクセス範囲が与えられ、その範囲にアクセスし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にプロキシイテレータがある場合でも機能することが保証されています。


2
多分私は密集しているかもしれませんが、zipペアの例で共通の参照が何であるかを明確にできますか?
happydave

4
理想的には、pair<T&,U&>およびpair<T,U>&共通の基準を持っているでしょうし、それは単純になりますpair<T&,U&>。ただし、の場合std::pair、からpair<T,U>&への変換はありませんpair<T&,U&>が、そのような変換は原則的には有効です。(ちなみに、これzipがC ++ 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

3
tuple、、pair 、- - 。とで要素にアクセスできるこの素晴らしい機能があります。構造化されたバインディングは、すべてではなく、s での作業の厄介な部分に役立ちます。tomatotoMAHtopair.first.secondtuple
Eric Niebler
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.