Почему нет std :: stou?


96

В C ++ 11 добавлены новые функции преобразования строк:

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

Он включает в себя stoi (строка в int), stol (строка в long), stoll (строка в long long), stoul (строка в long без знака), stoull (строка в long без знака). Примечательна его отсутствием функция stou (преобразование строки в беззнаковый). Есть ли причина, по которой он не нужен, а все остальные нужны?

связанные: В C ++ 11 нет функций "sto {short, unsigned short}"?


6
Мой вопрос должен был быть больше похож на «есть ли какой-нибудь неочевидный недостаток простого использования stoul». Очевидно, это испортит создание экземпляров шаблона, но есть ли что-нибудь еще, что я не рассматриваю? Комментарии о том, почему это было исключено, были бы хорошими, но второстепенными.
Дэвид Стоун

13
@NicolBolas Я не понимаю, почему это неконструктивно. Это совершенно правильный вопрос, поскольку я не вижу причин для этого несоответствия, и ответы могут дать представление о некоторых, возможно, существующих действительных, но не очевидных причинах.
Christian Rau

4
@SethCarnegie Что ж, то, что делает ваша платформа (и, возможно, большинство платформ), просто не имеет значения, потому что unsigned longпросто нет unsigned int.
Christian Rau

4
@SethCarnegie: на моем обычном компьютере unsigned longэто 64 бита и unsigned int32. Они бывают разных типов, и нельзя предполагать, что они идентичны друг другу.
Майк Сеймур,

2
@NicolBolas Как уже было сказано, OP (и я) не знают, что это спекулятивно, поскольку для этого может быть прекрасная веская причина, глубоко укоренившаяся во внутренностях языка C ++. Но поскольку вы говорите, что это спекулятивно, я полагаю, что такой причины нет. Но опять же, возможно, человек, ответственный за C ++ 11, все же сможет ответить на него. Это не вопрос "Вау-вау, где это чертовски stou", а вопрос, в котором задается, возможно, определенная причина этой очевидной несогласованности. Если вы знаете, что такой причины нет, то опубликуйте ее как ответ.
Christian Rau

Ответы:


29

Наиболее удачным ответом было бы то, что в библиотеке C нет соответствующего символа « strtou», а строковые функции C ++ 11 - это просто тонко завуалированные оболочки вокруг функций библиотеки C: std::sto*функции отражают strto*и используют std::to_stringфункции sprintf.


Изменить: как указывает Кенни TM, stoiиstol используются strtolв качестве базовой функции преобразования, но все еще остается загадкой, почему, хотя существует, stoulчто использует strtoul, нет соответствующего stou.


14
Вы знаете, почему Комитет C ++ решил пойти на такой C-ish подход? Что-то вроде boost::lexical_cast<>()кажется более подходящим для C ++.
Пол Манта,

2
Действительно ли эти детали реализации определены стандартом?
Lightness Races in Orbit

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) соответственно.
Майк Сеймур,

12
Не имеет значения, сказано ли в стандарте C ++ «должно быть реализовано путем вызова ...», потому что в стандарте C ++ все еще есть глобальное правило «как если бы»: если в стандарте говорится, что он std::sto*должен быть реализован как оболочка для функций библиотеки C, и действительная программа не может сказать, что они не были тайно реализованы иначе, реализация действительна.

2
Полностью не по теме, я думаю, что практические причины отказа от использования iostreams, таких как Boost / lexical_cast, заключаются в чистой производительности; Я считаю, что iostreams проигрывают strtoul и т. Д. Со значительным отрывом.
Kerrek SB 03

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также является лишь проверкой диапазона.
Hossein

1
@Hossein: Между stoiи stol, да. Но stolи stollне отличаются только проверкой диапазона, они вызывают разные библиотечные функции.
Бен Фойгт

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.