Na biblioteca padrão C ++, existem funções para converter de string para tipos numéricos:
stoi
stol
stoll
stoul
stoull
stof
stod
stold
mas acho tedioso usá-los no código do modelo. Por que não há funções de modelo, algo como:
template<typename T>
T sto(...)
converter seqüências de caracteres para tipos numéricos?
Não vejo nenhuma razão técnica para não tê-los, mas talvez esteja perdendo alguma coisa. Eles podem ser especializados para chamar as funções nomeadas subjacentes e usar enable_if
/ concepts
para desativar tipos não numéricos.
Existem alternativas compatíveis com modelos na biblioteca padrão para converter seqüências de caracteres em tipos numéricos e o contrário de maneira eficiente?
c++
string-conversion
Mircea Ispas
fonte
fonte
Respostas:
O C ++ 17 possui uma string genérica para função numérica, mas com um nome diferente. Eles foram com
std::from_chars
, que está sobrecarregado para todos os tipos numéricos.Como você pode ver, a primeira sobrecarga está tomando qualquer tipo inteiro como parâmetro de saída e atribuirá o valor a ele, se possível.
Pode ser usado assim:
Como você pode ver, ele pode funcionar em contexto genérico.
fonte
Não é um modelo e não funciona com localidades, mas se isso não for um impedimento de exibição, o C ++ 17 já terá o que você deseja:
std::from_chars
Existem sobrecargas para todos os tipos de número inteiro e ponto flutuante e a interface é a mesma, exceto para os últimos parâmetros que são diferentes para os tipos inteiro e de ponto flutuante, respectivamente (mas se o padrão for bom, você não precisará mudar qualquer coisa). Como essa não é uma função com reconhecimento de localidade, também é bastante rápida. Ele irá bater em qualquer outra string para avaliar a função de conversão e geralmente é por ordens de magnitude.
Há um vídeo muito bom do CPPCON sobre
<charconv>
(o cabeçalhofrom_chars
mora) de Stephan T. Lavavej, que você pode assistir sobre seu uso e desempenho aqui: https://www.youtube.com/watch?v=4P_kbF0EbZMfonte
stoi
e seus amigos (as conversões mencionadas na pergunta) também não funcionam com localidades, de modo que não é um impedimento.Você não ganha muito porque em uma expressão como
Não existe uma maneira (fácil) de deduzir o tipo desejado para o parâmetro do modelo. Você teria que escrever
que, até certo ponto, anula o objetivo de fornecer uma função genérica. Por outro lado, um
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.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.fonte
auto x = sto(s)
? Essa implementação específicaconverter::x
é interrompida porque é uma referência que sai do escopo, mas é corrigível. Apenas remova a referência e conte comstd::string
a semântica de movimentação.converter
, também não tenho certeza se o uso de um operador de conversão de modelo foi a melhor escolha, coisas que poderiam ser corrigidas. Talvez não seja tão ruim como eu pensava inicialmenteA solução compatível com todos (inclusive os compiladores C ++ mais antigos, como o C ++ - 98) é usar o boost :: lexical_cast, que é um modelo para converter entre os tipos numéricos e de string de ambos os modos.
Exemplo:
Consulte: https://www.boost.org/doc/libs/1_42_0/libs/conversion/lexical_cast.htm
fonte
Nas versões mais antigas do C ++, o stringstream é seu amigo. Se eu entendi corretamente, o seguinte pode ser interessante para você. É C ++ 11.
https://wandbox.org/permlink/nUNiUwWWTr7a0NXM
Este método funciona em C ++ 11 e é bastante geral. Na minha experiência, esse método é robusto, mas não o mais eficiente.
fonte