Você não ganha muito porque em uma expressão como
int x = sto("1");
Não existe uma maneira (fácil) de deduzir o tipo desejado para o parâmetro do modelo. Você teria que escrever
int x = sto<int>("1");
que, até certo ponto, anula o objetivo de fornecer uma função genérica. Por outro lado, um
template<typename T>
void sto(std::string x,T& t);
seria de bom uso, como você percebeu. No C ++ 17, existe std::from_chars
, o que faz mais ou menos exatamente isso (não é um modelo, mas um conjunto de sobrecargas e leva ponteiros para caracteres em vez de uma string, mas são apenas pequenos detalhes).
PS
Não há uma maneira fácil de deduzir o tipo desejado na expressão acima, mas existe uma maneira. Não acho que o núcleo da sua pergunta tenha sido exatamente a assinatura solicitada e não acho que seja uma boa maneira de implementá-la, mas sabia que havia uma maneira de fazer a int x = sto("1");
compilação acima e fiquei curioso para vê-la. em ação.
#include <iostream>
#include <string>
struct converter {
const std::string& x;
template <typename T> operator T() { return 0;}
};
template <> converter::operator int() { return stoi(x); }
template <> converter::operator double() { return stod(x); }
converter sto(const std::string& x) { return {x}; }
int main() {
std::string s{"1.23"};
int x = sto(s);
double y = sto(s);
std::cout << x << " " << y;
}
Isso funciona como planejado, mas tem desvantagens graves, talvez o mais importante seja que ele permite escrever auto x = sto(s);
, ou seja, é fácil usar errado.