2011-01-28 20 views
7

penso avrò a destra in esso e iniziare con il codice:Come restituire 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"; 
} 

Fondamentalmente, ho bisogno di restituire un ofstream. Ovviamente non è possibile copiare un ofstream, quindi ho giocato con il codice nel test di classe, e ho ottenuto quanto sopra per compilare e lavorare come ci si aspetterebbe (su gcc 4.5).

Ma ho la brutta sensazione che ciò è dovuto al fatto che il mio compilatore sta eseguendo "Return Value Optimization" (RTO) su "auto os = test()". Effettivamente, se si modifica quanto segue:

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

Non riesco più a ottenere Test1 e Test2 nell'output.

Il fatto è che il "test" di classe non è copiabile, quindi non c'è alcuna possibilità che l'ofstream venga duplicato. Voglio solo essere in grado di restituirlo da una funzione. E mi sembra di essere in grado di farlo con GCC.

Preferisco non avere riferimenti puntatori intelligenti a un heap allocato distream o riaprire il file, poiché attualmente funziona senza eseguire tali operazioni. Ho solo la sensazione di essere un po '"non standard" nel mio approccio, quindi un modo standard per fare quello che ho descritto sarebbe fantastico.

risposta

15

ho intenzione di rispondere alla mia domanda qui:

Nella pagina GCC C++0x Library Features, uno sguardo al punto 27.9, in cui si legge:

27,9 - flussi di file-based - Parziale - Missing operazioni di spostamento e scambio

Immagino che questo sia probabilmente il problema che sto avendo con gcc.

+0

Sì, lo farebbe. Buona scoperta, però. – GManNickG

+0

Ancora vero ora? –

+0

Non sembra che no. Sentiti libero di modificare la domanda e rispondere se puoi. – Clinton

2

Il problema è con questo:

test(test&& old) {}; 

Questo consente di costruire una nuova test da un rvalue test, sì, ma non dice nulla circa la vostra base, che è semplicemente essere di default costruito (senza aprire il file) . Quello che vuoi è questo:

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

che si muoverà il flusso dal old nella base.

+0

La tua risposta dà il seguente errore di compilazione su gcc 4.5: "'std :: ios_base :: ios_base (const std :: ios_base &)' è privato". Sei sicuro di averlo compilato, e se sì, su quale compilatore? – Clinton

+0

@Clinton: non ho ancora provato a compilare il codice, anche se l'ho già fatto molte volte. (Nota: "compila" non è necessariamente un test per essere corretto C++). Dovresti modificare la tua domanda per includere il nuovo codice che stai provando e tutti gli errori. – GManNickG

+0

Sei sicuro che ofstream abbia un costruttore rvalue? – Clinton

0

Il chiamante deve sapere che si sta restituendo un ofstream, o avrebbe più senso restituire un streambuf e lasciare che il chiamante lo avvolga all'interno di un flusso?