¿Por qué los compiladores ahora aceptan llamar al miembro str() en un std::ostream& devuelto desde std::stringstream::operator

2 minutos de lectura

Avatar de usuario de Fareanor
faranor

Considere la siguiente línea:

std::string s = (std::stringstream() << "foo").str();

Esto no debería compilar porque std::stringstream::operator<<() es heredado por std::ostream y devuelve un std::ostream& cual no tiene un str() miembro.

Parece que los compiladores principales ahora aceptan este código donde no lo hacían en el pasado. ¿Qué cambio estándar sucedió para hacer esta compilación?

Hice algunas pruebas con CCG, Sonido metálico y MSVC y pude encontrar la versión donde ocurrió el cambio:

Compilador Rechazos hasta (versión) Acepta de (versión)
CCG 11.1 11.2
Sonido metálico 12.0.1 13.0.0
MSVC v19.14 v19.15

Puedes encuentra la prueba aquí

  • Error muy extraño de hecho.

    – Jason Liam

    19 de septiembre a las 9:20

  • Tenga en cuenta que auto t = (std::stringstream() << "foo"); std::cout << typeid

    – Adrián Mole

    19 de septiembre a las 9:29

  • fwiw aquí puedes ver que el tipo de (std::stringstream() << "foo") cambió: godbolt.org/z/hE38cKTdj

    – 463035818_no_es_un_número

    19 de septiembre a las 9:33

Todos agregaron la sobrecarga de rvalue (ver aquí) aproximadamente al mismo tiempo.

La sobrecarga de rvalue fue introducido en agregado a C++11 y devuelve el mismo tipo de flujo que su operando de la izquierda.

Como se ha señalado en los comentarios, la razón por la que se agregó a los compiladores aparentemente después de toda una década es que se agregó a C++ 11. retroactivamente y muy recientemente, probablemente después de haber sido aprobado para su inclusión en C++20.

Estoy convirtiendo esto en un wiki de la comunidad en caso de que alguien tenga la inclinación y la paciencia para buscar el razonamiento detrás de la adición retroactiva y modificar la respuesta.

  • La forma en que leí las especificaciones fue retroactivamente introducido en C++ 11 después de 2018-05-25; lo que significa que todos llegaron tarde al agregar una función que se agregó tarde.

    –Hans Olsson

    20 sep a las 15:39

  • @HansOlsson Eso suena más que plausible. ¿Te importa si agrego eso a la respuesta?

    – molbdnilo

    20 de septiembre a las 16:29

  • @hansolsson: cuando dice introducido en c ++ 11, ¿quiere decir introducido en c ++ 20 o literalmente agregado a la especificación c ++ 11 (reemplazada 3 veces) en 2018?

    – Karl Nicol

    20 de septiembre a las 19:47

  • @KarlNicoll: Hans enfatizó 'retroactivamente', así que lo tomo como "sí, retrocedió en el tiempo y agregó a la especificación anterior". Algo extraño, pero sucede a veces para características muy importantes. Sin embargo, no soy Hans, así que no estoy 100% seguro.

    – quetzalcóatl

    20 de septiembre a las 20:06

  • @quetzalcoatl: sí, supongo que tiene razón, y aparece como una característica de c ++ 11 en cppref. Simplemente parece una locura que una función de este tipo se haya retroalimentado tan atrás, pero luego se necesitan muchos años más para obtener un amplio soporte del compilador. ¡No parece que valga la pena el esfuerzo! Cosas locas.

    – Karl Nicol

    20 de septiembre a las 21:47

¿Ha sido útil esta solución?