2011-01-28 17 views
7

creo que voy a conseguir la derecha en ella y empezar con el código:Cómo devolver un fstream (C++ 0x)

#include <iostream> 
#include <fstream> 
#include <string> 

class test : public std::ofstream 
{ 
    public: 
     test(const std::string& filename) { this->open(gen_filename(filename)); }; 
     test(const test&) = delete; 
     //test(test&& old) = default; // Didn't compile 
     test(test&& old) {}; 
    private: 
     std::string gen_filename(const std::string& filename) 
     { return filename + ".tmp"; } 
}; 

int main() 
{ 
    auto os = test("testfile"); 
    os << "Test1\n"; 
    os << "Test2\n"; 
} 

Básicamente, tengo que devolver un ofstream. Por supuesto, no puedes copiar un flujo de corriente, así que jugueteé con el código en la prueba de clase, y obtuve lo anterior para compilar y trabajar como es de esperar (en gcc 4.5).

Pero tengo una mala sensación de que esto se deba a que mi compilador realiza "Optimización del valor de retorno" (RTO) en "auto os = test()". De hecho, si se modifica a lo siguiente:

int main() 
{ 
    auto os = test("testfile"); 
    os << "Test1\n"; 
    auto os2 = std::move(os); 
    os2 << "Test2\n"; 
} 

Ya no recibo tanto Test1 como Test2 en la salida.

El problema es que la clase "prueba" no se puede copiar, por lo que no hay posibilidad de que el flujo de corriente se duplique. Solo quiero poder devolverlo desde una función. Y creo que puedo hacer eso con GCC.

Prefiero no tener punteros inteligentes de referencia en un montón asignado de corriente, o volver a abrir el archivo, ya que actualmente funciona sin hacer esas cosas. Solo tengo la sensación de que estoy siendo un poco "no estándar" en mi enfoque, por lo que una forma estándar de hacer lo que he descrito sería genial.

Respuesta

15

Voy a responder a mi propia pregunta aquí:

En la página GCC C++0x Library Features, echar un vistazo a este artículo 27.9, que dice:

27.9 - corrientes basados ​​en archivos - Parcial - Missing mover e intercambiar operaciones

Creo que ese es probablemente el problema que estoy teniendo con gcc.

+0

Sí, eso lo haría. Buen descubrimiento, sin embargo. – GManNickG

+0

¿Sigue siendo cierto ahora? –

+0

No parece que no. Siéntase libre de editar la pregunta y la respuesta si puede. – Clinton

2

El problema es con esto:

test(test&& old) {}; 

Esto le permite construir un nuevo test de un rvalue test, sí, pero no dice nada acerca de su base, que es simplemente siendo construida por defecto (sin abrir el archivo) . Lo que se quiere es la siguiente:

test(test&& old) : std::ofstream(std::move(old)) {}; 

la que se desplazará la corriente de old en la base.

+0

Su respuesta arroja el siguiente error de compilación en gcc 4.5: "'std :: ios_base :: ios_base (const std :: ios_base &)' es privado". ¿Estás seguro de que tienes esto para compilar, y si es así, en qué compilador? – Clinton

+0

@Clinton: No he intentado compilar tu código, aunque ya lo he hecho muchas veces. (Tenga en cuenta que "compila" no es necesariamente una prueba para que sea correcto C++). Debe editar su pregunta para incluir el nuevo código que está intentando y todos los errores. – GManNickG

+0

¿Seguro que de corriente tiene un constructor de rvalue? – Clinton

0

¿Necesita la persona que llama saber que está devolviendo un ofstream, o tendría más sentido devolver un streambuf y dejar que la persona que llama lo envuelva dentro de un flujo?