web-dev-qa-db-ja.com

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

C++ 20は std::common_reference 。その目的は何ですか?誰かがそれを使用する例を挙げられますか?

41
康桓瑋

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

STLでは、イテレータには2つの関連するタイプ、特にreferencevalue_typeがあります。前者はイテレータのoperator*の戻り型であり、value_typeはシーケンスの要素の(非const、非参照)型です。

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

value_type tmp = *it;

...これらの2つの型の間にはsomeの関係が存在する必要があることがわかります。非プロキシイテレータの場合、関係は単純です。referenceは常にvalue_typeであり、オプションでconstと参照を修飾できます。 InputIterator概念を定義する初期の試み は、式*itconst value_type &に変換可能であることが必要であり、最も興味深いイテレータには十分です。

C++ 20のイテレータをこれよりも強力にしたかったのです。たとえば、ロックステップで2つのシーケンスを反復するZip_iteratorの必要性を考慮してください。 Zip_iteratorを逆参照すると、2つの反復子のpair型の一時的なreferenceを取得します。したがって、Zipvector<int>およびvector<double>に含めると、次のような型が関連付けられます。

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

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

C++ 20での答えは、anyの有効なイテレータタイプ、プロキシかどうか、タイプ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を使用して計算できます。

つまり、C++ 20のSTLでcommon_referenceが果たす役割です。一般に、一般的なアルゴリズムやプロキシイテレータを作成していない限り、無視しても問題ありません。これは、イテレータが契約上の義務を確実に満たすことを保証する裏側にあります。


編集: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>{});

Range rにプロキシイテレータがある場合でも、これは機能することが保証されています。

43
Eric Niebler