¿Por qué std :: istringstream parece resolverse de manera diferente a std :: ifstream en el operador ternario (? :)?
Estoy acostumbrado a escribir pequeñas herramientas de línea de comandos que toman un nombre de archivo o leenstd::cin
, así que he estado usando este patrón durante bastante tiempo:
int main(int argc, char* argv[])
{
std::string filename;
// args processing ...
std::ifstream ifs;
if(!filename.empty())
ifs.open(filename);
std::istream& is = ifs.is_open() ? ifs : std::cin;
std::string line;
while(std::getline(is, line))
{
// process line...
}
return 0;
}
Después de leer una pregunta sobre Stack Overflow, intenté modificar mi patrón habitual para adaptarlo a la necesidad de leerlo desde un archivo o desde unstd::istringstream
. Para mi sorpresa, no se compilará y da este error:
temp.cpp:164:47: error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘void*’
std::istream& is = ifs.is_open() ? ifs : iss; // won't compile
Lo que me parece que está tratando de convertir elstd::istringstream
objeto (iss
) a un booleano y obtener suoperator void*()
.
int main(int argc, char* argv[])
{
std::string filename;
std::string data;
// args processing ...
std::ifstream ifs;
std::istringstream iss;
if(!filename.empty())
ifs.open(filename);
std::istream& is = ifs.is_open() ? ifs : iss; // won't compile
std::string line;
while(std::getline(is, line))
{
// process line...
}
return 0;
}
¿Por qué está tratando?std::istringstream
diferente destd::cin
ystd::ifstream
? Todos derivan destd::istream
.
Entonces recordé haber convertido mi patrón para dar cabida a tres posibilidades, leer desde un archivo, cadena ostd::cin
. Y recuerdo que funcionó (aunque es bastante torpe). Entonces, aplicando la solución triple a este problema, se me ocurrió un dulce de azúcar que funciona totalmente:
int main(int argc, char* argv[])
{
std::string filename;
std::string data;
// args processing ...
std::ifstream ifs;
std::istringstream iss;
if(!filename.empty())
ifs.open(filename);
std::istream& is = ifs.is_open() ? ifs : true ? iss : std::cin; // fudge works
std::string line;
while(std::getline(is, line))
{
// process line...
}
return 0;
}
¿Por qué funciona este dulce de azúcar? ¿GCC está infringiendo alguna regla sobre cómo el operador ternario (?:
) resuelve sus tipos? ¿O me estoy perdiendo algo?