Dlaczego nie ma std :: stou?

96

C ++ 11 dodał kilka nowych funkcji konwersji ciągów:

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

Zawiera stoi (ciąg do wartości typu int), stol (ciąg do długości długiej), stoll (ciąg do długości długiej bez znaku), stoul (ciąg do długości bez znaku), stoull (ciąg do długości bez znaku). W przypadku jego braku godna uwagi jest funkcja stou (ciąg bez znaku). Czy jest jakiś powód, dla którego nie jest to potrzebne, a wszystkie inne są?

related: Brak funkcji „sto {short, unsigned short}” w C ++ 11?

David Stone
źródło
6
Moje pytanie miało być bardziej podobne do „czy istnieje jakaś nieoczywista wada zwykłego używania stoulu”. Oczywiście, to zepsuje tworzenie instancji szablonu, ale czy jest coś jeszcze, czego nie rozważam? Komentarze na temat powodów pominięcia byłyby miłe, ale drugorzędne.
David Stone,
13
@NicolBolas Nie rozumiem, dlaczego to nie jest konstruktywne. Jest to całkowicie uzasadnione pytanie, ponieważ nie widzę żadnego powodu tej niespójności, a odpowiedzi mogą dać wgląd w jakiś prawdopodobnie istniejący ważny, ale nie tak oczywisty powód.
Christian Rau,
4
@SethCarnegie Cóż, to, co robi Twoja platforma (i być może większość platform), jest po prostu nieistotne, ponieważ po unsigned longprostu nie unsigned int.
Christian Rau,
4
@SethCarnegie: na moim typowym komputerze unsigned longma 64 bity i unsigned int32 bity. Są to różne typy i nie można zakładać, że są takie same.
Mike Seymour,
2
@NicolBolas Jak powiedziałem, OP (i ja) nie wiemy, że to spekulacje, ponieważ może istnieć doskonały uzasadniony powód, dla którego jest to głęboko zakorzenione w wewnętrznych wnętrzach języka C ++. Ale skoro mówisz, że to spekulacje, myślę, że nie ma takiego powodu. Ale znowu, być może osoba odpowiedzialna za C ++ 11 nadal może na to odpowiedzieć. To nie jest stoupytanie „Wah wah, gdzie jest to cholerne ”, ale pytanie o możliwie określony powód tej oczywistej niespójności. Jeśli wiesz , że nie ma takiego powodu, to napisz jako odpowiedź.
Christian Rau,

Odpowiedzi:

29

Najprostszą odpowiedzią byłoby to, że biblioteka C nie ma odpowiadającego jej znaku „ strtou”, a funkcje łańcuchowe w C ++ 11 są tylko cienko zawoalowanymi opakowaniami wokół funkcji biblioteki C: std::sto*lustro funkcji strto*i std::to_stringfunkcje używane sprintf.


Edycja: Jak wskazuje Kenny TM, oba stoii stolużywaj strtoljako podstawowej funkcji konwersji, ale wciąż jest tajemnicze, dlaczego skoro istnieje, stoulktóry używa strtoul, nie ma odpowiednika stou.

Kerrek SB
źródło
14
Czy wiesz, dlaczego Komitet C ++ zdecydował się na takie podejście C ++? Coś takiego boost::lexical_cast<>()wydaje się być bardziej C ++ sposobem robienia rzeczy.
Paul Manta,
2
Czy te szczegóły implementacji są naprawdę zdefiniowane przez standardy?
Wyścigi lekkości na orbicie
4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Efekty: pierwsze dwie funkcje wywołują strtol (str.c_str (), ptr, base), a ostatnie trzy funkcje wywołują strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) i strtoull (str.c_str (), ptr, base).
Mike Seymour,
12
Nie ma znaczenia, czy standard C ++ mówi, że „musi być zaimplementowany przez wywołanie ...”, ponieważ standard C ++ nadal ma globalną regułę as-if: jeśli standard mówi, std::sto*musi być zaimplementowany jako otoki dla funkcji biblioteki C, i prawidłowy program nie może powiedzieć, że nie są one potajemnie zaimplementowane inaczej, implementacja jest poprawna.
2
Całkowicie nie na temat, myślę, że praktycznymi powodami nieużywania iostreamów, takich jak Boost / lexical_cast, jest czysta wydajność; Uważam, że iostreams przegrywa ze strtoul itp. Ze znacznym marginesem.
Kerrek SB,
22

Nie mam pojęcia, dlaczego stoiistnieje, ale nie stou, ale jedyną różnicą między stoula hipotetycznym stoubyłoby sprawdzenie, czy wynik mieści się w zakresie 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;
}

(Podobnie stoijest również stolz innym sprawdzaniem zakresu, ale ponieważ już istnieje, nie trzeba się martwić, jak dokładnie to zaimplementować).

Mike Seymour
źródło
Różnica między stoii stollub stoli stolljest również tylko sprawdzeniem zakresu.
Hossein
1
@Hossein: Między stoia stol, tak. Ale stoli stollnie różnią się tylko sprawdzaniem zakresu, wywołują różne funkcje biblioteki.
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...
}

Użycie masek do zrobienia tego z oczekiwanym rozmiarem wartości w bitach wyrażonym w masce sprawi, że będzie to działać dla 64-bitowych długości w porównaniu z 32-bitowymi liczbami int, ale także dla 32-bitowych długości w porównaniu z 32-bitowymi liczbami int.

W przypadku długości 64-bitowych, ~ 0xffffffffl zmieni się na 0xffffffff00000000 i sprawdzi, czy któryś z 32 górnych bitów jest ustawiony. Przy długościach 32-bitowych ~ 0xffffffffl staje się 0x00000000, a kontrola maski zawsze będzie wynosić zero.

Gregg Wonderly
źródło