Чому немає std :: stou?


96

C ++ 11 додав кілька нових функцій перетворення рядків:

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

Він включає stoi (рядок до int), stol (рядок до довгого), stoll (рядок до довгого довгого), stoul (рядок до беззнакового довгого), stoull (рядок до беззнакового довгого довгого). Примітною за його відсутності є функція stou (рядок до беззнаку). Чи є якісь причини, що це не потрібно, але всі інші потрібні?

пов'язані: У C ++ 11 немає функцій "sto {короткий, непідписаний короткий}"?


6
Моє запитання було спрямовано на те, щоб "чи є якийсь неочевидний недолік простого використання stoul". Очевидно, що це зіпсує інстанціювання шаблону, але чи є щось інше, про що я не розглядаю? Коментарі щодо того, чому його залишили поза увагою, були б приємними, але другорядними.
Девід Стоун

12
@NicolBolas Я не можу зрозуміти, чому це не конструктивно. Це цілком слушне запитання, оскільки я не бачу жодної причини цієї невідповідності, і відповіді можуть дати уявлення про деякі, можливо, існуючі дійсні, але не такі очевидні причини для цього.
Крістіан Рау

4
@SethCarnegie Ну, те, що робить ваша платформа (і, можливо, більшість платформ), просто не має значення, оскільки unsigned longсправедливість - ні unsigned int.
Крістіан Рау,

4
@SethCarnegie: на моєму типовому комп’ютері - unsigned longце 64 біти і unsigned int32. Вони різного типу, і не можна вважати їх однаковими.
Майк Сеймур

2
@NicolBolas Як вже було сказано, ОП (і я) не знає, що це спекулятивно, оскільки для цього могла бути цілком поважна причина, яка глибоко проникла в мовні внутрішні середовища С ++. Але оскільки ви кажете, що це спекулятивно, то, мабуть, такої причини немає. Але знову ж таки, можливо, відповідальний за C ++ 11 все ще може відповісти на нього. Це не stouзапитання "Wah wah, де це проклятий ", а питання, що задає можливу певну причину цієї очевидної невідповідності. Якщо ви знаєте, що такої причини немає, то добре, опублікуйте її як відповідь.
Крістіан Рау

Відповіді:


29

Найбільш відповідна відповідь полягала б у тому, що бібліотека C не має відповідного “ strtou”, а рядкові функції C ++ 11 - це лише тонко завуальовані обгортки навколо функцій бібліотеки C: std::sto*дзеркало функцій strto*та використання std::to_stringфункцій sprintf.


Змінити: Як KennyTM вказує, як stoiі stolвикористання в strtolякості опції перетворення , що лежить в основі, але це все ще загадкове , чому в той час як існує , stoulщо використання strtoul, немає відповідних stou.


14
Чи знаєте ви, чому Комітет С ++ вирішив піти на такий підхід на С-іші? Щось подібне boost::lexical_cast<>()здається більш простим способом роботи на C ++.
Paul Manta

2
Чи справді ці деталі реалізації визначені стандартом?
Гонки легкості на орбіті

4
@LightnessRacesinOrbit: For sto*, C ++ 11 21.5 / 1: Ефекти: перші дві функції викликають strtol (str.c_str (), ptr, base), а останні три функції викликають strtoul (str.c_str (), ptr, base ), strtoll (str.c_str (), ptr, base) та strtoull (str.c_str (), ptr, base) відповідно.
Mike Seymour

12
Немає значення, чи в стандарті С ++ сказано "має бути реалізовано за допомогою виклику ...", оскільки стандарт С ++ все ще має загальне правило як би: якщо стандарт говорить, що він std::sto*повинен бути реалізований як обгортки для функцій бібліотеки С, і діюча програма не може сказати, що вони не таємно реалізовані інакше, реалізація є дійсною.

2
Повністю не в темі, я думаю, що практичними причинами невикористання iostream, як Boost / lexical_cast, є простота продуктивність; Я вважаю, що iostream втрачає значні переваги проти strtoul тощо.
Kerrek SB

22

Я не уявляю, чому stoiіснує, але ні stou, але єдиною відмінністю між stoulі гіпотетичним stouбуде перевірка, що результат знаходиться в діапазоні 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;
}

(Так само, stoiце також схоже на stol, лише з іншою перевіркою діапазону; але оскільки воно вже існує, не потрібно турбуватися про те, як саме його реалізувати.)


Різниця між stoiта stol, або stolта stoll- це також лише перевірка діапазону.
Хоссейн

1
@Hossein: Між stoiі stolтак. Але stolі stollне відрізняються лише перевіркою діапазону, вони викликають різні функції бібліотеки.
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...
}

Використання масок для цього з очікуваним розміром значення у бітах, виражених у масці, зробить цю роботу для 64-бітових довжин проти 32-бітних інтів, а також для 32-бітних довжин проти 32-бітних інтів.

У випадку 64-бітових довжин ~ 0xffffffffl стане 0xffffffff00000000 і, таким чином, побачить, чи встановлено будь-який з 32-х бітів. З 32-бітними довжинами, ~ 0xffffffffl стає 0x00000000 і перевірка маски завжди буде нульовою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.