Puede culparme por esto. El comité ha tratado de cambiar (dos veces creo), pero cada vez la solución terminó rompiendo cosas.
La semántica de intercambio y movimiento se ha adaptado a nuestro sistema de E/S una década después de su diseño. Y no fue un ajuste perfectamente limpio.
Tenga en cuenta que basic_ios::swap
es protegida función de miembro y no hay variante de ámbito de espacio de nombres. Por lo tanto, esto solo puede invocarse desde una clase derivada (típicamente istream/ostream). Tenga en cuenta que i/o_stream::swap
también está protegido y sin variante de ámbito de espacio de nombres. Y su especificación es llamar a la clase base swap
y luego intercambiar cualquier información local (como gcount
en istream
).
Finalmente, en el nivel string/filestream
obtienes lo que considerarías una "normal" swap
: miembro público y variantes de espacio de nombres de espacio. En este nivel, tiene un miembro de datos string/file buffer
(el rdbuf
) y la clase base. El swap
en este nivel simplemente intercambia la base y los miembros de datos.
La característica que complica de todo esto es que el rdbuf()
en la clase base es en realidad un puntero referencia a sí misma a la streambuf
(basic_filebuf
o basic_stringbuf
) y de clase derivada que Es por eso que no quiere que la clase base para intercambiar estos punteros de referencia automática.
Esto hace que la base swap
sea extraña, pero todos están protegidos, salvo los clientes derivados. Y el código para swap
del cliente derivado es subsecuentemente aparentemente simple. Y en el nivel derivado, swap
se hace público y se comporta de la manera en que los clientes públicos lo esperan.
Un baile similar está hecho para la construcción de movimiento y la asignación de movimiento. La construcción de movimientos se complica aún más por el hecho de que la clase base es una base virtual, y por lo tanto su constructor no es llamado por la clase derivada más directamente.
Fue divertido. Se ve raro. Pero finalmente funciona. ;-)
Corrección Leve:
Alberto Ganesh Barbati is responsible para proteger swap
a nivel i/ostream
. Fue una muy buena llamada de su parte que me había perdido por completo con mi primer diseño.
Alf P. Steinbach haciendo una pregunta. Increíble. : | – Nawaz
Esto es realmente sorprendente. Si cambio dos cosas, realmente esperaría que cambien; si tuviera un error y descubriera que no estaba intercambiando 'rdbuf', asumiría que era un error de implementación. – GManNickG
Muy sorprendente de hecho. Revisé el primer FinalDraft que tuve (n3092) y es exactamente lo mismo. Me pregunto si fue idéntico en C++ 03, ¿quizás un remanente heredado? –