Почему нет 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, и проверка маски всегда будет нулевой.

Грегг Уандерли
источник