operador de secuencia de cadena > > falla como función, pero funciona como instancia?

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

  •  10-07-2019
  •  | 
  •  

Pregunta

Estoy escribiendo un código simple que extraerá un montón de nombres, pares int de un archivo. Estoy modificando el código existente que solo usa:

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

Pero quiero usar otro archivo de entrada (similar) que tenga las mismas dos primeras columnas, pero que estén seguidos por otros datos (que serán ignorados). Entonces escribo:

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

Pero esto no puede compilarse, dando la típica vomitación de plantilla obscena estándar:

 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...]

Correcto. La línea no es un std :: string, sino alguna variación de std :: basic_string, etc. Sin embargo, la creación de instancias explícita de la secuencia de cadena funciona.

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

¿Por qué? ¿Qué tiene de malo el primer caso? El ejemplo basic_io en el siempre útil cplusplus.com funciona, ¿por qué mi ¿código?

Actualización: Otro punto de referencia: el flujo de cadena temporal funciona cuando el primer valor extraído es un int en lugar de una cadena:

unsigned int chrom;  // works as int...
unsigned int size;
string line;
while ( getline(cin, line) ) {
    if( stringstream(line) >> chrom >> size ) {
        // save values
    }
}
¿Fue útil?

Solución

Tres grupos de funciones miembro y un grupo de funciones globales sobrecargan este " operador de extracción " (> >), consulte http: //www.cplusplus. com / reference / istream / istream / operator% 3E% 3E / .

  • secuencia de cadena (línea); --crea un objeto temporal
  • stringstream ss (line); - un objeto normal.

cuando " chrom " es int, operador > > está sobrecargado como extractor aritmético que es funciones miembro. Tanto el objeto normal como el objeto temporal funcionan bien.

Cuando " chrom " es cadena, operador > > debe sobrecargarse como istream & amp; operador > > (istream & amp; is, char * str) , esta es una función global que debe tomar la referencia del objeto como parámetro. Sin embargo, dado el objeto temporal, no se nos permite pasar objetos temporales por referencia no constante en C ++ estándar. La función de sobrecarga no puede obtener la referencia del objeto temporal a menos que la función de sobrecarga se defina como istream & amp; operador > > (const istream & amp; is, char * str) . Desafortunadamente, ese no es el hecho. Las funciones no se pueden sobrecargar en el caso del objeto temporal y, por lo tanto, emiten el error como error: no coincide con la función ...

Otros consejos

Para ampliar la respuesta de John Weldon, el operador extrace " > > " hace dos cosas:

  1. Extrae el siguiente valor y lo coloca en la variable a la derecha del operador.
  2. Incrementa la posición actual de la secuencia a la izquierda.

Por lo tanto, modifica sus operandos izquierdo y derecho. En su caso, el operando de la izquierda es un valor temporal, y el compilador frunce el ceño al modificarlo.

Algunos operadores en C y C ++ requieren que el valor a la izquierda del operador sea un valor l, es decir, que puedan modificarse.

Aquí es una explicación más completa.

Porque el primer valor extraído del stringstream es std :: string. Si fuera, digamos, un int, la versión stringstream (line) funcionaría.

No hay operador de función miembro > > en stringstream para std :: string. Por lo tanto, la secuencia temporal no puede funcionar como un lvalue.

No es que entienda completamente lo anterior ... pero tal vez es un punto de partida para una mejor respuesta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top