C++ 20は std::common_reference
。その目的は何ですか?誰かがそれを使用する例を挙げられますか?
common_reference
は、プロキシイテレータに対応するSTLのイテレータの概念化を思い付いた私の取り組みから生まれました。
STLでは、イテレータには2つの関連するタイプ、特にreference
とvalue_type
があります。前者はイテレータのoperator*
の戻り型であり、value_type
はシーケンスの要素の(非const、非参照)型です。
一般的なアルゴリズムでは、多くの場合、次のようなことを行う必要があります。
value_type tmp = *it;
...これらの2つの型の間にはsomeの関係が存在する必要があることがわかります。非プロキシイテレータの場合、関係は単純です。reference
は常にvalue_type
であり、オプションでconstと参照を修飾できます。 InputIterator
概念を定義する初期の試み は、式*it
がconst value_type &
に変換可能であることが必要であり、最も興味深いイテレータには十分です。
C++ 20のイテレータをこれよりも強力にしたかったのです。たとえば、ロックステップで2つのシーケンスを反復するZip_iterator
の必要性を考慮してください。 Zip_iterator
を逆参照すると、2つの反復子のpair
型の一時的なreference
を取得します。したがって、Zip
をvector<int>
およびvector<double>
に含めると、次のような型が関連付けられます。
Zip
イテレータのreference
:pair<int &, double &>
Zip
イテレータのvalue_type
:pair<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
にプロキシイテレータがある場合でも、これは機能することが保証されています。