Geçici bir borulu menzil işlemine geri gönderebilir miyim?


9

Varsayalım ki bir generate_my_rangesınıf var range(özellikle, regular). Sonra aşağıdaki kod doğrudur:

auto generate_my_range(int some_param) {    
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op);
}
auto cells = generate_my_range(10) | ranges::to<std::vector>;

my_custom_rng_gen(some_param)(İlk) boru operatörü tarafından değere göre mi alınır yoksa generate_my_rangekapsamdan ayrıldıktan sonra sarkan bir referansım var mı?

İşlevsel çağrı ile aynı olur ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)mu?

Bir değer referansı kullanırsam doğru olur mu? Örneğin:

auto generate_my_range(int some_param) {
  auto my_transform_op = [](const auto& x){ return do_sth(x); };
  auto tmp_ref = my_custom_rng_gen(some_param);
  return tmp_ref | ranges::views::transform(my_transform_op);
}

Aralıklar bu işlemler için değerlere göre alınırsa, bir kapsayıcıya lvalue ref iletirsem ne yapmalıyım? Bir ranges::views::all(my_container)kalıp kullanmalı mıyım ?


My_custom_rng_gen (some_param) zaten sınırlı mı? Eğer böyle bir şey ifade ediyor mu godbolt.org/z/aTF8RN take (5) olmadan?
Porsche9II

@ Porsche9II Evet, bu sınırlı bir aralık. Diyelim ki bir konteyner
Bérenger

Yanıtlar:


4

Aralık kütüphanesinde iki tür işlem vardır:

  • tembel ve altta yatan kabın varlığını gerektiren görünümler .
  • istekli olan ve sonuç olarak yeni kaplar üreten (veya mevcut olanları değiştiren) eylemler

Görüntüler hafiftir. Bunları değere göre iletirsiniz ve alttaki kapların geçerli ve değişmeden kalmasını istersiniz.

Kaynaktan aralıkları-v3 belgelerinde

Görünüm, altta yatan bir dizi öğenin, mutasyona uğratılmadan veya kopyalanmadan özel bir şekilde bir görünümünü sunan hafif bir sargıdır. Görünümler oluşturmak ve kopyalamak ucuzdur ve sahip olunmayan referans semantiğine sahiptir.

ve:

Temel aralıktaki yineleyicilerini veya sentinellerini geçersiz kılan herhangi bir işlem de, bu aralığın herhangi bir bölümünü ifade eden herhangi bir görünümü geçersiz kılacaktır.

Alttaki kabın imhası, açıkça tüm yineleyicileri geçersiz kılar.

Kodunuzda sen specifially kullandığınız görünümleri - Sen kullanmak ranges::views::transform. Boru sadece olduğu gibi yazmayı kolaylaştırmak için sadece sözdizimsel bir şekerdir. Ne ürettiğinizi görmek için borudaki son şeye bakmalısınız - sizin durumunuzda bir görünümdür.

Boru operatörü olmasaydı, muhtemelen şöyle bir şey olurdu:

ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)

bu şekilde bağlı birden fazla dönüşüm olsaydı, ne kadar çirkinleşeceğini görebilirsiniz.

Böylece, my_custom_rng_gendönüştürdüğünüz ve sonra geri döndürdüğünüz bir tür konteyner üretiyorsa, o konteyner imha edilir ve sizin görüşünüzden sarkan referanslarınız olur. Eğer my_custom_rng_genbu kapsamları dışında yaşamlarını, her şey yolunda olduğuna dair bir konteynıra başka görünümüdür.

Ancak, derleyici geçici bir kapsayıcıya bir görünüm uyguladığınızı anlayabilmeli ve derleme hatasıyla size çarpabilmelidir.

İşlevinizin bir aralığı kapsayıcı olarak döndürmesini istiyorsanız, sonucu açıkça "gerçekleştirmeniz" gerekir. Bunun için ranges::toişlevin içindeki operatörü kullanın .


Güncelleme: Yorumunuzla ilgili daha açıklayıcı olmak için "dokümantasyon aralık / boru oluşturmanın bir bakış açısını alıp kaydettiğini nerede söylüyor?"

Boru, şeyleri okunması kolay bir ifadeye bağlamak için sadece sözdizimsel bir şekerdir. Nasıl kullanıldığına bağlı olarak, bir görünüm döndürebilir veya döndürmeyebilir. Sağ taraftaki argümana bağlıdır. Sizin durumunuzda:

`<some range> | ranges::views::transform(...)`

Böylece ifade her ne views::transformdöndürürse onu döndürür.

Şimdi, dönüşümün belgelerini okuyarak:

Aşağıda, Range-v3'ün sağladığı tembel aralık birleştiricilerinin veya görünümlerinin bir listesi ve her birinin nasıl kullanılması amaçlandığı hakkında bir bulanıklık.

[...]

views::transform

Bir kaynak aralığı ve tekli işlev verildiğinde, her sonuç öğesinin tekli işlevi bir kaynak öğeye uygulamanın sonucu olduğu yeni bir aralık döndürün.

Bir dizi verir, ancak bunu bir tembel operatör olduğundan, bu döndüren aralığı Yani olan bir görünümü tüm semantik ile.


Tamam. Benim için biraz gizemli olan şey, bir konteynırı boruya (yani kompozisyon tarafından oluşturulan aralık nesnesi) geçirdiğimde nasıl çalıştığıdır. Bir şekilde kabın bir görünümünü saklaması gerekiyor. İle bitti ranges::views::all(my_container)mi? Peki boruya bir görünüm geçirilirse? Bir kap ya da görünümden geçtiğini biliyor mu? Gerekiyor mu? Nasıl?
Bérenger

"Derleyici geçici bir kapsayıcıya bir görünüm uyguladığınızı ve derleme hatasıyla vurduğunuzu anlayabilmelidir" Ben de öyle düşünmüştüm: aptalca bir şey yaparsam, bu tür bir sözleşme değeri) yerine getirilmez. Bunun gibi şeyler range-v3 ile yapılır. Ancak bu durumda kesinlikle hiçbir sorun yoktur. Derler VE çalışır. Yani tanımlanmamış davranışlar olabilir, ancak ortaya çıkmaz.
Bérenger

Kodunuzun kazara doğru çalışıp çalışmadığından veya her şeyin yolunda olup olmadığından emin olmak için içeriğini görmem gerekir my_custom_rng_gen. Borunun ve transformkaputun altında nasıl etkileşime girdiği önemli değildir. Tüm ifade bir aralığı bağımsız değişken olarak alır (bir kapsayıcı veya bir kapsayıcıya bir görünüm) ve o kapsayıcıya farklı bir görünüm döndürür. Dönüş değeri hiçbir zaman kabın sahibi olmaz, çünkü bu bir görünümdür.
CygnusX1

1

Seriler -v3 belgelerinden alınmıştır :

Görünümler [...] sahip olmayan referans anlambilimine sahiptir.

ve

Tek aralıklı bir nesneye sahip olmak, işlem boru hatlarına izin verir. Bir boru hattında, bir aralık tembel olarak uyarlanır veya bir şekilde hevesle mutasyona uğrar, sonuç daha fazla adaptasyon veya mutasyon için hemen kullanılabilir. Tembel adaptasyon görüşlerle ve istekli mutasyon eylemlerle ele alınır.

// taken directly from the the ranges documentation
std::vector<int> const vi{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
using namespace ranges;
auto rng = vi | views::remove_if([](int i){ return i % 2 == 1; })
              | views::transform([](int i){ return std::to_string(i); });
// rng == {"2","4","6","8","10"};

Yukarıdaki kodda, rng sadece temel verilere ve filtre ve dönüştürme işlevlerine bir referans depolar. Rng yinelenene kadar hiçbir iş yapılmaz.

Geçici aralığın bir kapsayıcı olarak düşünülebileceğini söylediğiniz için, işleviniz sarkan bir referans döndürür.

Başka bir deyişle, temel alınan aralığın görünümü aştığından emin olmanız gerekir veya sorun yaşarsınız.


Evet, görünümler sahip değildir, ancak dokümantasyon aralık / boru oluşturmanın bir görünüm aldığını ve sakladığını nereden söylüyor? Aşağıdaki politikaya sahip olmak mümkündür (ve bence iyi bir şey): aralık bir değer referansı ile verilirse değere göre depolayın.
Bérenger

1
@ Bérenger Ürün yelpazesi belgelerinden biraz daha ekledim. Ama asıl mesele şu: Bir görüşe sahip olmak yok . Size bir değer verip vermemeniz önemli değildir.
Mart'ta Rumburak
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.