Biblioteca estándar de C++: ¿Cómo escribir contenedores para cout, cerr, cin y endl?
No me gusta , using namespace std
pero también estoy cansado de tener que escribir std::
delante de cada cout
,, y . Entonces, pensé en darles nombres nuevos más cortos como este:cin
cerr
endl
// STLWrapper.h
#include <iostream>
#include <string>
extern std::ostream& Cout;
extern std::ostream& Cerr;
extern std::istream& Cin;
extern std::string& Endl;
// STLWrapper.cpp
#include "STLWrapper.h"
std::ostream& Cout = std::cout;
std::ostream& Cerr = std::cerr;
std::istream& Cerr = std::cin;
std::string _EndlStr("\n");
std::string& Endl = _EndlStr;
Esto funciona. Pero, ¿hay algún problema en lo anterior que me falta? ¿Existe una mejor manera de lograr lo mismo?
Alex te ha dado una respuesta sobre cómo resolver sintácticamente ese problema. Sin embargo, quiero señalar otros dos argumentos respecto a esta cuestión:
No importa si estás empleando una directiva de uso (
using namespace std
) o su hermana menos malvada, una declaración de uso (using std::cout
), la sobrecarga puede llevar a sorpresas desagradables. No es mucha molestia escribirstd::
en comparación con pasar media noche depurando para descubrir que se llama a su códigostd::distance()
en lugar de a su propiadistance()
función , solo porque cometió un pequeño error ystd::distance()
accidentalmente es una mejor coincidencia.Una línea de código se escribe una vez , pero, dependiendo de su vida útil, se lee decenas, cientos y, en algunos casos, incluso miles de veces . Así que el tiempo que lleva escribir una línea de código simplemente no importa en absoluto , lo importante es sólo el tiempo que lleva leer e interpretar una línea de código . Incluso si se necesita tres veces más tiempo para escribir una línea con todo lo adecuado
std::
, si hace que la lectura sea solo un 10% más rápida, aún así vale la pena.
Entonces, la pregunta importante es: ¿ Es más fácil leer e interpretar una línea de código con todo el códigostd::
en su lugar o es más difícil ? De otra respuesta :Aquí hay un dato más: Hace muchos, muchos años, también me resultaba molesto tener que anteponer todo lo de la biblioteca estándar con
std::
. Luego trabajé en un proyecto en el que se decidió desde el principio que tantousing
las directivas como las declaraciones estaban prohibidas excepto en el ámbito de las funciones. ¿Adivina qué? A la mayoría de nosotros nos tomó muy pocas semanas acostumbrarnos a escribir el prefijo y después de algunas semanas más, la mayoría de nosotros incluso estuvo de acuerdo en que en realidad hacía que el código fuera más legible . (Hay una razón para esto: si le gusta la prosa más corta o más larga es subjetivo, pero los prefijos agregan objetivamente claridad al código. No solo al compilador, sino a usted también le resulta más fácil ver a qué identificador se hace referencia).En una década, ese proyecto creció hasta tener varios millones de líneas de código. Dado que estas discusiones surgen una y otra vez, una vez sentí curiosidad por saber con qué frecuencia
using
se usaba realmente el alcance de función (permitido) en el proyecto. Busqué las fuentes y solo encontré una o dos docenas de lugares donde se usaba. Para mí, esto indica que, una vez que lo intentaron, a los desarrolladores no les resultóstd::
lo suficientemente doloroso emplear directivas de uso ni siquiera una vez cada 100 kLoC, incluso donde se permitía su uso .Creo que es triste que todos los libros y tutoriales que encuentres se salten
std::
, porque eso hace que la gente se acostumbre a leer el código de esa manera. Cuando enseñé C++ durante varios años (después de la experiencia mencionada anteriormente), les dije a mis alumnos que no quería ver ningunausing
directiva o declaración en su código. (La única excepción a esa regla esusing std::swap
, por cierto, que necesitará para detectarswap(a,b)
sobrecargas fuera del espacio de nombresstd
). Una vez que se acostumbraron, no les importó y, cuando se les preguntó al respecto, dijeron que encontrar código sinstd::
prefijo confuso. Algunos incluso agregaron elstd::
prefijo al código que escribieron en un libro o tutorial que no lo tenía .
En pocas palabras: ¿Qué tiene de difícil escribir std::
que todo el mundo se enoja tanto? Ya llevo más de 15 años haciéndolo y no me pierdo using
nada.
Por qué no
using std::cin;
using std::cout;
¿etcétera? Luego, en su código puede usar cin
, cout
y así sucesivamente, sin inyectar accidentalmente el resto del std
espacio de nombres en su código.