C ++ 20 std :: common_reference'nin amacı nedir?


Yanıtlar:


46

common_reference STL'nin proxy yineleyicilerini barındıran yineleyicilerin kavramsallaştırılmasıyla ilgili çabalarımdan çıktı.

STL'de, yineleyicilerin ilişkili iki tür özel ilgi alanı vardır: referenceve value_type. Eski yineleyici en dönüş türü olan operator*ve value_typedizinin elemanları (const olmayan, referans olmayan) türüdür.

Genel algoritmaların genellikle böyle şeyler yapma ihtiyacı vardır:

value_type tmp = *it;

... biz olması gerektiğini biliyorum bazı Bu iki tip arasındaki ilişki. Proxy olmayan yineleyiciler için ilişki basittir: referenceher zaman value_type, isteğe bağlı olarak const ve başvuru nitelikli. Kavramın tanımlanmasına yönelik erken girişimlerInputIterator , ifadenin *itdönüştürülebilir olmasını const value_type &ve çoğu ilginç yineleyici için yeterli olmasını gerektiriyordu.

C ++ 20'deki yineleyicilerin bundan daha güçlü olmasını istedim. Örneğin, zip_iteratorkilit adımında iki diziyi yineleyen a'nın ihtiyaçlarını düşünün . A'dan vazgeçtiğinizde , iki yineleyicinin türünden zip_iteratorbir geçici alırsınız . Yani, a ve a şu ilişkili türlere sahip olacaktır:pairreferencezipvector<int>vector<double>

zipyineleyicinin reference: pair<int &, double &>
zipyineleyicinin value_type:pair<int, double>

Gördüğünüz gibi, bu iki tür sadece üst düzey cv- ve ref yeterlilikleri ekleyerek birbirleriyle ilişkili değildir. Ve yine de iki türün keyfi olarak farklı olmasına izin vermek yanlış geliyor. Açıkçası burada bir ilişki var. Fakat ilişki nedir ve yineleyiciler üzerinde çalışan genel algoritmalar iki tür hakkında güvenli bir şekilde ne kabul edebilir?

C ++ 20'de cevabı için olmasıdır herhangi vekil veya olmasın geçerli yineleyici tip, tür reference &&ve value_type &bir paylaşma ortak referansı . Başka bir deyişle, bazı Yineleyici için itbazı tip var CRiyi biçimli aşağıdakileri yapar:

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
}

CRortak referanstır. Tüm algoritmalar bu türün varlığına güvenebilir ve bunu std::common_referencehesaplamak için kullanabilir .

Yani, common_referenceC ++ 20'de STL'de oynayan rol budur . Genel olarak, genel algoritmalar veya proxy yineleyicileri yazmıyorsanız, güvenle yok sayabilirsiniz. Yineleyicilerin sözleşmeden doğan yükümlülüklerini yerine getirmelerini sağlayan kapakların altındadır.


EDIT: OP de bir örnek istedi. Bu yapmacık biraz, ama onun C ++ 20 hayal ve rastgele erişimli aralığı verilir rÇeşidi RBir şey bilmiyormuş hangi ve istediğiniz sortaralıkta.

Ayrıca, bazı nedenlerden dolayı, monomorfik bir karşılaştırma fonksiyonu kullanmak istediğinizi düşünün std::less<T>. (Belki ettik aralığı tip silinir ve ayrıca karşılaştırma işlevi yazın-silmek ve bir içinden geçmeleri gerekiyor virtual? Yine, bir streç.) Ne olmalıdır Tolmak std::less<T>? Bunun için common_reference, ya da iter_common_reference_tonun açısından uygulanan yardımcıyı kullanırdınız .

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

Aralıkta rproxy yineleyicileri olsa bile, bunun çalışması garanti edilir .


2
Belki yoğunum, ancak zip çifti örneğinde ortak referansın ne olduğunu açıklayabilir misiniz?
happydave

4
İdeal olarak pair<T&,U&>ve pair<T,U>&ortak bir referansı olacaktır ve basitçe olacaktır pair<T&,U&>. Ancak, için std::pair, hiçbir dönüşüm vardır pair<T,U>&için pair<T&,U&>, böyle bir dönüşüm ilkesinin ses olsa. (Bu arada, zipC ++ 20'de bir görüşümüz yok .)
Eric Niebler

4
@EricNiebler: " Bu arada, C ++ 20'de zip görünümüne sahip olmamızın nedeni budur . " pairAmacı için özel olarak tasarlanabilecek bir tür yerine bir zip yineleyicisinin kullanmasının bir nedeni var mı? , gerektiği gibi uygun örtülü dönüşümlerle?
Nicol Bolas

5
@Nicol Bolas Kullanmaya gerek yoktur std::pair; uygun dönüşümleri olan herhangi bir uygun çift benzeri tip yapar ve range-v3 böyle bir çift benzeri tip tanımlar. Komitede LEWG, Standart Kütüphane'ye std::pair, sadece std::pairiş yapmanın artıları ve eksileri hakkında gereken özen göstermeden, normatif olsun veya olmasın, neredeyse ama tam olmayan bir tür ekleme fikrini beğenmedi .
Eric Niebler

3
tuple, pair, tomato, to- MAH- to. pairBirlikte elemanları erişebilmesi bu güzel özelliği vardır .firstve .second. Yapısal bağlamalar, tuples ile çalışmanın garipliğinin bazılarına yardımcı olur , ancak hepsi değil.
Eric Niebler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.