Почему строка `std:: sto`... не является шаблоном?
Интересно, есть ли причина, по которой серия std::sto
(например, std::stoi
, std::stol
) не является шаблоном функции, например:
template<typename T>
T sto(std::string const & str, std::size_t *pos = 0, int base = 10);
а затем:
template<>
int sto<int>(std::string const & str, std::size_t *pos, int base)
{
// do the stuff.
}
template<>
long sto<long>(std::string const & str, std::size_t *pos, int base)
{
// do the stuff.
}
/* etc. */
В моем смысле, это будет лучший дизайн, потому что на данный момент, когда мне нужно преобразовать строку в любое числовое значение, которое требуется пользователю, я должен вручную управлять каждым случаем.
Есть ли причина не иметь такую функцию шаблона? Есть ли предполагаемый выбор, или это просто так?
Ответы
Ответ 1
I have to manage manually each case. Is there a reason to not have such a template function?
В случае таких вопросов Эрик Липперт (С#) обычно говорит что-то в строках:
Если функция отсутствует, она отсутствует, поскольку ее еще не реализовано. И это потому, что либо еще никто раньше не хотел, или потому, что считалось нецелесообразным, либо потому, что он не мог быть закончен, прежде чем публиковать текущую версию ".
Здесь, я думаю, это "не стоит", но я не спрашивал об этом коммите и не нашел ответа в старых вопросах и вопросах. Я не тратил много времени на поиск.
Я говорю это, потому что я полагаю, что наиболее распространенная функциональность этих функций (если не все) уже содержится в классах потоков, например istringstream
. Точно так же, как cin
/и т.д., Он также имеет all-have operator >>
, перегруженный для всех базовых числовых типов (и более).
Кроме того, манипуляторы потока, такие как std::hex
(std:: setbase), уже решают проблему передачи различных параметров конфигурации, зависящих от типа, к фактическим функциям преобразования. Нет проблем со смешанными сигнатурами функций (как, например, Дэвидом Хаим в его ответе). Вот только один operator>>
.
Итак, поскольку, если мы имеем это в streams
, если мы уже можем читать числа /etc из строк с помощью простого foo >> bar >> setbase(42) >> baz >> ...
, то я думаю, что не стоит пытаться добавлять более сложные слои к старой среде выполнения C функции.
Нет доказательств для этого. Просто догадка.
Ответ 2
Глядя на описание этих функций в cppref, я отмечаю следующее:
... Интерпретирует знаковое целочисленное значение в строке str.
1) вызывает std::strtol(str.c_str(), &ptr, base)
...
и strol
стандартная функция "C", которая также доступна на С++.
Далее, мы видим: (для функций С++ sto*
):
Возвращаемое значение
Строка, преобразованная в указанный целочисленный тип со знаком.
Исключения
-
std::invalid_argument
, если преобразование не может быть выполнено -
std::out_of_range
, если преобразованное значение выпадет из диапазона типа результата или если основная функция (std:: strtol или std:: strtoll) устанавливает errno в ERANGE.
Поэтому, хотя у меня нет оригинального источника для этого и, действительно, никогда не работал с этими функциями, я бы предположил, что:
TL; DR: эти функции являются обертками С++ - ish вокруг уже существующих функций C/С++ - strtol*
- так они напоминают эти функции как можно ближе.
Ответ 3
Проблема специализации шаблонов заключается в том, что специализация требует, чтобы вы соответствовали оригинальной сигнатуре функции шаблона, поэтому каждая специализация должна реализовывать интерфейс (string,pos,base)
.
Если вы хотите иметь какой-то другой тип, который не следует этому интерфейсу, у вас проблемы.
Предположим, что в будущем мы хотели бы иметь sto<std::pair<int,int>>
. Мы хотим иметь pos
и base
для первого и второго строкового целого числа. мы хотим, чтобы подпись была в форме string,pos1,base1,pos2,base2
. Поскольку sto
подпись уже установлена, мы не можем этого сделать.
Вы всегда можете заключить std::sto*
в свою реализацию sto
для целых типов, но вы не можете сделать это наоборот.
Ответ 4
Цель этих функций - обеспечить простые преобразования для обычных случаев. Они не предназначены для конверсии общего назначения. std::ostringstream
намного лучше для такого рода вещей.
Ответ 5
В моем смысле, был бы лучший дизайн, потому что на данный момент, когда мне нужно преобразовать строку в любое числовое значение пользователя хочу, я должен вручную управлять каждым случаем.
Нет, не будет. Цель шаблонов (намеренная установка T-MP отдельно) не, чтобы заменить перегрузку; вы всегда должны перегружать шаблоны. Собственно, это то, что язык уже делает для вас! Между кандидатской функцией и возможной возможностью создания шаблона будет предпочтительнее первая. Использование языковых функций для этого плохо.
Я не вижу, как могут помочь шаблоны. Независимо от типа, который пользователь решает ввести, он не будет известен до времени исполнения, а типы шаблонов выводятся во время компиляции. С++ - это статически типизированный язык. В этом случае шаблоны просто добавят ненужный уровень сложности при нормальной перегрузке функций.