opérateur de stringstream > > échoue en tant que fonction, mais fonctionne en tant qu'instance?

StackOverflow https://stackoverflow.com/questions/1823073

  •  10-07-2019
  •  | 
  •  

Question

J'écris un code simple qui va extraire un groupe de nom, paires int d'un fichier. Je modifie le code existant qui utilise simplement:

string chrom;
unsigned int size;
while ( cin >> chrom >> size ) {
    //  save values
}

Mais je veux utiliser un autre fichier d'entrée (similaire) qui contient les deux mêmes colonnes, mais qui est suivi d'autres données (qui seront ignorées). Alors j'écris:

string chrom;
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}

Mais cela ne parvient pas à compiler, ce qui donne le modèle obscène typique sten lib:

 error: no match for "operator>>" in "std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >(((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& line))), std::operator|(_S_out, _S_in)) >> chrom"
istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
[...another dozen lines...]

D'accord. line n'est pas un std :: string, mais une variante de std :: basic_string, etc. Cependant, instancier explicitement le stringstream.

string chrom;
unsigned int size;
string line;
while ( getline(genome, line) ) {
    stringstream ss(line);
    if ( ss >> chrom >> size ) {
       // save values
    }
    // Discard remainder of line
}

Pourquoi? Quel est le problème avec le premier cas? exemple basic_io du site toujours utile cplusplus.com fonctionne, pourquoi mes code?

Mise à jour: Autre point de référence: le stringstream temporaire fonctionne lorsque la première valeur extraite est un int au lieu d’une chaîne:

unsigned int chrom;  // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}
Était-ce utile?

La solution

Trois groupes de fonctions membres et un groupe de fonctions globales surchargent cet "opérateur d'extraction". (> >), voir http: //www.cplusplus. com / référence / istream / istream / opérateur% 3E% 3E / .

  • stringstream (ligne); --créé un objet temporaire
  • stringstream ss (line); - un objet normal.

quand "chrom" est int, opérateur > > est surchargé en tant qu'extracteur arithmétique qui est une fonction membre. L’objet normal ou l’objet temporaire fonctionne correctement.

Quand "chrom" est une chaîne, opérateur > > devrait être surchargé comme istream & amp; opérateur > > (istream & amp; is, char * str) , il s’agit d’une fonction globale qui doit prendre la référence de l’objet en paramètre. Cependant, étant donné objet temporaire, nous ne sommes pas autorisés à transmettre des objets temporaires par référence non-const en C ++ standard. La fonction de surcharge ne peut pas obtenir la référence de l'objet temporaire à moins que la fonction de surcharge ne soit définie comme istream & amp; opérateur > > (const istream & is; char * str) . Malheureusement, ce n'est pas le cas. La ou les fonctions ne peuvent pas être surchargées dans le cas des objets temporaires, générant ainsi une erreur telle que erreur: aucune correspondance pour la fonction ...

Autres conseils

Pour approfondir la réponse de John Weldon, l'opérateur d'extraction " > > " fait deux choses:

  1. Extrait la valeur suivante et la place dans la variable à droite de l'opérateur.
  2. Incrémente la position actuelle du flux à gauche.

Par conséquent, il modifie ses opérandes gauche et droit. Dans votre cas, l'opérande de gauche est une valeur temporaire et le compilateur désapprouve en le modifiant.

Certains opérateurs en C et C ++ exigent que la valeur à gauche de l'opérateur soit une valeur, c'est-à-dire qu'ils puissent être modifiés.

ici est une explication plus complète.

Parce que la première valeur extraite du stringstream est un std :: string. S'il s'agissait, par exemple, d'un int, la version stringstream (line) fonctionnerait.

Aucun opérateur de fonction membre > > dans stringstream pour std :: string. Par conséquent, le flux temporaire ne peut pas fonctionner comme une lvalue.

Ce n'est pas que je comprenne bien ce qui précède ... mais c'est peut-être un point de départ pour une meilleure réponse.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top