Neden std :: stou yok?


96

C ++ 11, bazı yeni dize dönüştürme işlevleri ekledi:

http://en.cppreference.com/w/cpp/string/basic_string/stoul

Stoi (string'den int'e), stol (string'den long'a), stoll (string'den long'a), stoul (string'den unsigned long'a), stoull (string'den unsigned long'a kadar) içerir. Onun yokluğunda dikkate değer bir stou (dizeden işaretsiz) işlevidir. Gerekli olmamasına rağmen diğerlerinin hepsinin bir nedeni var mı?

related: C ++ 11'de "sto {short, unsigned short}" işlevi yok mu?


6
Sorum, "sadece stoul kullanmanın bariz olmayan bir dezavantajı var mı?" Açıkçası bu, şablon somutlaştırmayı bozacak, ama düşünmediğim başka bir şey var mı? Neden dışarıda bırakıldığına dair yorumlar güzel ama ikincil olacaktır.
David Stone

13
@NicolBolas Bunun neden yapıcı olmadığını anlayamıyorum. Bu tutarsızlığın herhangi bir nedenini göremediğim için bu tamamen geçerli bir sorudur ve cevaplar, muhtemelen var olan bazı geçerli geçerli, ancak bunun için o kadar açık olmayan bir neden hakkında fikir verebilir.
Christian Rau

4
@SethCarnegie Platformunuzun (ve belki de platformların çoğunluğunun) yaptığı şey alakasızdır, çünkü unsigned longadil bir hayırdır unsigned int.
Christian Rau

4
@SethCarnegie: Tipik bilgisayarımda unsigned long64 bit ve unsigned int32. Bunlar farklı türler ve birbirleriyle aynı oldukları varsayılamaz.
Mike Seymour

2
@NicolBolas Dediğim gibi, OP (ve ben) bunun spekülatif olduğunu bilmiyor, çünkü C ++ dilinin derinliklerine gömülmesinin mükemmel bir geçerli nedeni olabilir. Ama spekülatif olduğunu söylediğinize göre sanırım böyle bir sebep yok. Ama yine de, belki de C ++ 11'den sorumlu bir kişi yine de yanıtlayabilir. Bu "Wah wah, bu lanet olası stou" sorusu değil, bu bariz tutarsızlığın muhtemelen kesin bir nedenini soran bir sorudur. Eğer varsa bilmek böyle neden yoktur, o zaman iyi bir cevap olarak yayınlamayın.
Christian Rau

Yanıtlar:


29

En doğru cevap, C kitaplığının karşılık gelen " strtou" içermediğidir ve C ++ 11 dizgi işlevlerinin tümü, C kitaplığı işlevlerinin etrafındaki ince örtülü sarmalayıcılardır: std::sto*İşlevler aynası strto*ve std::to_stringişlevler kullanılır sprintf.


Düzenleme: As KennyTM işaret, hem stoive stolkullanımı strtolvardır iken neden yatan dönüşüm fonksiyonu olarak, ama yine de gizemli stoulolduğu kullanımları strtoul, hiçbir karşılık gelen yoktur stou.


14
C ++ Komitesinin neden böyle bir C-ish yaklaşımına gitmeye karar verdiğini biliyor musunuz? boost::lexical_cast<>()Gibi bir şey , işleri yapmanın daha C ++ bir yolu gibi görünüyor.
Paul Manta

2
Bu uygulama ayrıntıları gerçekten standart olarak tanımlanmış mı?
Orbit'te Hafiflik Yarışları

4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Etkiler: ilk iki işlev strtol (str.c_str (), ptr, base) ve son üç işlev strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) ve strtoull (str.c_str (), ptr, base).
Mike Seymour

12
C ++ standardının "... çağrılarak uygulanmalı" demesi önemli değildir, çünkü C ++ standardı hala genel sanki kuralına sahiptir: standart std::sto*, C kütüphanesi işlevleri için sarmalayıcılar olarak uygulanmalıdır diyorsa ve geçerli bir program gizlice uygulanmadığını söyleyemez, uygulama geçerlidir.

2
Tamamen konu dışı, Boost / lexical_cast gibi iostreams kullanmamanın pratik nedenlerinin saf performans olduğunu düşünüyorum; Iostreams'in strtoul vb. Karşısında önemli bir farkla kaybettiğine inanıyorum.
Kerrek SB

22

Neden stoivar olduğu hakkında hiçbir fikrim yok stou, ancak stoulvarsayım arasındaki tek fark stou, sonucun şu aralıkta olup olmadığını kontrol etmek olurdu unsigned:

unsigned stou(std::string const & str, size_t * idx = 0, int base = 10) {
    unsigned long result = std::stoul(str, idx, base);
    if (result > std::numeric_limits<unsigned>::max()) {
        throw std::out_of_range("stou");
    }
    return result;
}

(Aynı şekilde, sadece farklı bir aralık kontrolü ile stoide benzerdir stol; ancak zaten mevcut olduğundan, tam olarak nasıl uygulanacağı konusunda endişelenmenize gerek yoktur.)


stoiVe stol, veya stolve arasındaki fark stollda yalnızca bir aralık kontrolüdür.
Hossein

1
@Hossein: stoive arasında stol, evet. Ama stolve stollfarklı kütüphane işlevleri çağırmak, aralık kontrol altında sadece farklılık yoktur.
Ben Voigt

0
unsigned long ulval = std::stoul(buf);
unsigned long mask = ~0xffffffffl;
unsigned int uival;
if( (ulval & mask) == 0 )
    uival = (unsigned int)ulval;
else {
    ...range error...
}

Bunu, maskede ifade edilen bit cinsinden beklenen değer boyutuyla yapmak için maskeleri kullanmak, bunu 64 bit uzunluğa karşı 32 bit inçler için, aynı zamanda 32 bit uzunluğa karşı 32 bit inçler için de çalıştıracaktır.

64 bit uzunluğunda ~ 0xffffffffl, 0xffffffff00000000 olur ve böylece ilk 32 bitten herhangi birinin ayarlanıp ayarlanmadığını görür. 32 bit uzunluğunda, ~ 0xffffffffl 0x00000000 olur ve maske kontrolü her zaman sıfır olur.

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.