Std :: ssize () neden C ++ 20'de tanıtıldı?


99

C ++ 20std::ssize() , aşağıdaki gibi ücretsiz işlevi tanıttı :

template <class C>
    constexpr auto ssize(const C& c)
        -> std::common_type_t<std::ptrdiff_t,
                              std::make_signed_t<decltype(c.size())>>;

Cl ass C üye fonksiyonunun static_castdönüş değerini dönüştürmek için olası bir uygulama kullanıyor gibi görünüyorsize() imzalı karşılığına .

Yana size()C üyesi fonksiyonu daima negatif olmayan değerleri döndürür, neden kimse Talep imzalı değişkenler bunları saklamak için mi? Birinin gerçekten istemesi durumunda, bu bir basit meseledir static_cast.

Neden std::ssize()C ++ 20'de tanıtıldı?


4
@ Jarod42 Tanımsız yerine uygulama tanımlı değil mi? (imzalı taşma tanımsız. ancak imzalı dönüşüm, uygulama tanımlı)
phön

8
Keşke ssizeofoperatör de eklerlerse .
geza

3
Bu biraz ilgili olabilir: stackoverflow.com/questions/30395205/…
Marco13

10
@ JohnZ.Li Çok tutarsız görünme riski altında: Tam sayı türleriyle ilgili tüm C ++ tür sisteminin bozuk olduğunu düşünüyorum. Elbette, bazı tuhaflıkların (a'nın kaç biti olduğunu bilmemek gibi char) C'den miras alındığı ve en azından bir şekilde hafifletildiği (u)intX_tiddia edilebilir , ancak yine de eşit derecede ince ve kritik hataların sonsuz bir kaynağıdır . Bu tür şeyler ssizeyalnızca yamalardır ve bu, insanların titizlikle takip edebileceği () yaygın "en iyi uygulama kılavuzlarına" girmesi biraz zaman alır (belki "sonsuza kadar").
Marco13

6
Marco13 @: Diğer taraftan, C / C ++ tipi sistem, bir kenara diğer birçok diller croak mimarileri üzerinde çalışmaya C / C ++ kodu kullanılmasına izin, (mesela Java'nın sabit tipleri sisteme karşıt olarak) yok izin yetkin eğitmenler bazı önemli olsun bir öğrencinin kafasına dersler. Gibi, tüm dünya 64bit değil. Ve hayır, tüm dünya 8-bit karakter kullanmıyor. Öyle kolay ölü bunlar ile başa çıkmak için, ve sadece eğitmenler bu öğretirdi eğer, size daha iyi bir geliştirici yapar başından itibaren . (Ve, sadece sen, emin olmak için mi biliyorum (u)intX_ttürleridir opsiyonel öyle mi?)
DevSolar

Yanıtlar:


69

Gerekçe bu yazıda açıklanmıştır . Alıntı:

Span C ++ 17'ye uyarlandığında, hem dizin hem de boyut olarak işaretli bir tamsayı kullandı. Kısmen bu, derleme zamanında boyutu bilinmeyen bir türü belirtmek için "-1" in bir sentinel değer olarak kullanımına izin vermekti. Ancak size () işlevi işaretli bir değer döndüren bir STL kapsayıcısına sahip olmak sorunluydu, bu nedenle sorunu "çözmek" için P1089 tanıtıldı. Çoğunluk desteği aldı, ancak fikir birliği için gereken 2'ye 1'lik marjı almadı.

Bu makale, P1227, üye olmayan std :: ssize ve üye ssize () fonksiyonlarını eklemek için bir öneriydi. Bunların dahil edilmesi, belirli kodu çok daha basit hale getirecek ve boyut hesaplamalarında istenmeyen işaretsizliğin önlenmesine izin verecektir. Buradaki fikir, ssize () hem std :: ssize () aracılığıyla hem de üye işlevleri olarak tüm kapsayıcılar için kullanılabilir hale getirilirse P1089 direncinin azalacağıydı.


30
for(int i = 0; i < container.ssize() - 1; ++i)Örnek ayrıca oldukça zorlayıcı
Caleth

7
@John bana gerçekten string :: npos ile aynı şeyi yapabileceklerini ve size_t (-1) özel bir değer olarak kullanabileceklerini düşünüyor.
rubenvb

15
@ JohnZ.Li STL boyut türlerinin işaretsiz olması uzun süredir bir hata olarak kabul edilmektedir. Şimdi maalesef onu düzeltmek için çok geç. Şu andan itibaren yapabileceğimiz en iyi şey, ücretsiz bir işlev sağlamaktır.
LF

16
@LF: Bir konferanstaki Herb Sutter'dı (belki Bjarne bunu da söylemiştir). Ama biraz yanılıyor. Şimdi, 32-bit / 64-bit bilgisayarlarda, işaretli boyut daha iyi olurdu (Yani haklı). Ancak eski günlerde (16 bit boyutlar), işaretli boyut kötü olurdu (örneğin, yalnızca 32k baytlık diziler ayırabilirdik).
geza

11
@LF: Herb'ün bundan bahsettiğini buldum: youtube.com/watch?v=Puio5dly9N8&t=2667 . "Pratikte pek gündeme gelmiyor" dediği zaman bugünlerde doğrudur. Ancak> 20 yıl önce (16 bit sistemler) hiç doğru değildi. Dolayısıyla, STL tasarlanırken işaretsiz kullanmak o kadar da hata değildi.
geza

50

Eric Niebler'den karşılıksız olarak çalındı :

'Unsigned types signal that a negative index/size is not sane'STL ilk tasarlandığında hakim olan bilgelikti. Ancak mantıksal olarak, pek çok şeyin olumlu olması gerekmez. Bir koleksiyona eklenen veya koleksiyondan kaldırılan öğelerin sayısını belirtmek için işaretli bir tamsayıda bir sayı tutmak isteyebilirim. O zaman bunu koleksiyonun büyüklüğü ile birleştirmek isterim. Koleksiyonun boyutu işaretsiz ise, şimdi imzalı ve işaretsiz aritmetiği karıştırmak zorunda kalıyorum, bu bir böcek çiftliği. Derleyiciler bu konuda uyarıyor, ancak STL'nin tasarımı programcıları bu duruma çok fazla zorladığından, uyarı o kadar yaygındır ki çoğu insan onu kapatır. Bu utanç verici çünkü bu gerçek böcekleri gizler.

Arayüzlerde imzasız girişlerin kullanılması pek çok insanın sandığı gibi bir nimet değildir. Bir kullanıcı yanlışlıkla API'ye biraz negatif bir sayı iletirse, aniden çok büyük bir pozitif sayı olur. API, numarayı işaretli olarak almış olsaydı, sayının sıfırdan büyük veya sıfıra eşit olduğunu iddia ederek durumu tespit edebilir.

İmzalanmamış girişleri kullanımımızı biraz oynamayla (örneğin, maskeler) sınırlar ve başka her yerde imzalı girişler kullanırsak, hataların oluşma olasılığı daha düşüktür ve meydana geldiklerinde tespit edilmesi daha kolaydır.


6
Swift, negatif işaretli sayıların büyük işaretsiz sayılar olarak yeniden yorumlanmasından endişe duymasa da bu yaklaşımı benimser (çünkü başlangıçta sizi bu çılgın eğlenceli eve gerçekten götüren şey, örtük yayınlar yoktur). IntSadece pozitif sayıların anlamlı olduğu (bir diziyi indekslemek gibi) bile (makine kelime boyutunda) tam sayıların ortak para birimi türleri olması gerektiği yaklaşımını benimsiyorlar . Bundan herhangi bir sapma sağlam bir şekilde tespit edilmelidir. Her yerde yayınlar için endişelenmenize gerek kalmaması güzel.
Alexander - Monica'yı eski haline

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.