Почему «std :: sto» ... не является шаблоном?

19

Интересно, есть ли причина, по которой серия 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. */

В моем смысле, это будет лучший дизайн, потому что на данный момент, когда мне нужно преобразовать строку в любое числовое значение, которое требуется пользователю, я должен вручную управлять каждым случаем.

Есть ли причина не иметь такую ​​функцию шаблона? Есть ли предполагаемый выбор, или это просто так?

    
задан Boiethios 20.06.2016 в 13:05
источник
  • Я полагаю, std :: sto вы имеете в виду std :: stoi, std :: stol и т. д.? –  erip 20.06.2016 в 13:09
  • Версии с плавающей точкой не имеют базового параметра. –  interjay 20.06.2016 в 13:10
  • Вероятно, что-то похожее на «старые» функции C, которые вызываются этими функциями (strtol, strtoll, ...). –  Holt 20.06.2016 в 13:18
  • Что бы вы получили от необходимости писать sto <long> вместо stol? –  molbdnilo 20.06.2016 в 14:00
  • @molbdnilo: вам не разрешено добавлять новые перегрузки в std, но вам разрешено специализировать существующие шаблоны std. Дело в том, std :: swap и std :: hash. –  Matthieu M. 20.06.2016 в 16:54
Показать остальные комментарии

5 ответов

7

I have to manage manually each case. Is there a reason to not have such a template function?

В случае таких вопросов Эрик Липперт (C #) обычно говорит что-то в строках:

  

Если функция отсутствует, значит, она отсутствует, поскольку она еще не реализована. И это потому, что либо еще никто раньше не хотел, или потому, что это считалось нецелесообразным, либо потому, что он не мог быть закончен до публикации текущей версии ».

Здесь, я думаю, это «не стоит», но я не спрашивал об этом коммите и не нашел ответа в старых вопросах и вопросах. Я не тратил много времени на поиск.

Я говорю это, потому что я полагаю, что наиболее распространенная функциональность этих функций (если не все) уже содержится в классах потоков, например istringstream . Точно так же, как cin / etc, у этого также есть все-% operator >> , перегруженная для всех базовых числовых типов (и более).

Кроме того, манипуляторы потока, такие как std::hex (std :: setbase), уже решают проблему передачи различных параметров конфигурации, зависящих от типа, к фактическим функциям преобразования. Нет проблем со смешанными сигнатурами функций (как, например, Дэвидом Хаим в его ответе). Вот только один operator>> .

Итак, поскольку, если мы имеем это в streams , если мы уже можем читать числа / etc из строк с простым foo >> bar >> setbase(42) >> baz >> ... , то я думаю, что не стоит пытаться добавлять более сложные слои в старую C-среду выполнения функции.

Нет доказательств для этого. Просто догадка.

    
ответ дан quetzalcoatl 20.06.2016 в 13:58
источник
11

Посмотрев описание этих функций в cppref , я отмечаю следующее:

  

... Интерпретирует знаковое целочисленное значение в строке str.      

1) вызывает std::strtol(str.c_str(), &ptr, base) ...

и strol a "C" стандартная функция, которая также доступна на C ++.

Далее, мы видим: (для функций c ++ sto* ):

  

Возвращаемое значение

     

Строка, преобразованная в указанный целочисленный тип со знаком.

     

Исключения

     
  • std::invalid_argument , если преобразование не может быть выполнено
  •   
  • std::out_of_range , если преобразованное значение выпадет из диапазона типа результата или если основная функция (std :: strtol или   std :: strtoll) устанавливает errno в ERANGE.
  •   

Итак, хотя у меня нет оригинального источника для этого и, действительно, никогда не работал с этими функциями, я бы угадал , что:

TL; DR : эти функции являются оболочками C ++ - ish вокруг уже существующих функций C / C ++ - strtol* - поэтому они напоминают эти функции как можно ближе.

    
ответ дан Martin Ba 20.06.2016 в 13:26
источник
5

Проблема специализации шаблонов заключается в том, что специализация требует, чтобы вы соответствовали оригинальной сигнатуре функции шаблона, поэтому каждая специализация должна реализовать интерфейс (string,pos,base) .

Если вы хотите иметь какой-то другой тип, который не следует этому интерфейсу, у вас проблемы.

Предположим, что в будущем мы хотели бы иметь sto<std::pair<int,int>> . Мы хотим иметь pos и base для первого и второго строкового целого числа. мы хотим, чтобы подпись была в виде string,pos1,base1,pos2,base2 . Поскольку подпись sto уже установлена, мы не можем этого сделать.

Вы всегда можете обернуть std::sto* в своей реализации sto для интегральных типов, но вы не можете сделать это наоборот.     

ответ дан David Haim 20.06.2016 в 13:38
источник
  • не может быть обходным путем с вариационным шаблоном в c ++ 11? –  W.F. 20.06.2016 в 13:53
  • , вы могли бы сделать это еще до полиморфизма времени выполнения. Тем не менее, я думаю, что это немного перегиб для преобразования функции, большую часть времени вы не знаете тип, встроенный в строку во время компиляции. Как правило, функции преобразования строки в XX используются для разбора (CSV, XML, JSON и т. д.), поэтому в любом случае ваш код будет разделен на обработку целых чисел, строк и т. д. –  David Haim 20.06.2016 в 14:01
  • Возможно, вы правы, но все же мне было бы удобно иметь функцию, симметричную для std :: to_string, даже если они были шаблонами ... –  W.F. 20.06.2016 в 14:08
  • хорошо, честно говоря, я считаю, что лучшим стандартом является выброс чего-либо связанного с строкой и перезаписывания его с нуля. std :: sto - верхушка айсберга. –  David Haim 20.06.2016 в 14:14
4

Цель этих функций - обеспечить простые преобразования для обычных случаев. Они не предназначены для конверсии общего назначения. std::ostringstream намного лучше для такого рода вещей.

    
ответ дан Pete Becker 20.06.2016 в 14:23
источник
1
  

В моем смысле, был бы лучший дизайн, потому что на данный момент,   когда мне нужно преобразовать строку в любое числовое значение пользователя   хочу, я должен вручную управлять каждым случаем.

Нет, не будет. Цель шаблонов (намеренная установка T-MP отдельно) не , чтобы заменить перегрузку; вы всегда должны перегружать шаблоны. На самом деле, это язык уже для вас! Между кандидатской функцией и возможной возможностью создания шаблона будет предпочтительнее первая. Использование языковых функций для этого плохо.

Я не вижу, как могут помочь шаблоны. Независимо от типа, который пользователь решает ввести, он не будет известен до времени исполнения, а типы шаблонов выводятся во время компиляции. C ++ - это статически типизированный язык. В этом случае шаблоны просто добавят ненужный уровень сложности при нормальной перегрузке функций.

    
ответ дан edmz 20.06.2016 в 17:37
источник
  • я согласен с настроением, но перегрузка не является вариантом. вы не можете перегружать только возвращаемый тип. –  Steve Cox 21.06.2016 в 00:27