2011-01-28 17 views
7

myślę, że będę uzyskać prawo do niego i rozpocząć z kodem:Jak zwrócić 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"; 
} 

Zasadniczo, muszę zwrócić ofstream. Oczywiście nie można skopiować kodu źródłowego, więc zacząłem manipulować przy kodzie w teście klasy, i otrzymałem powyższe, aby skompilować i pracować tak, jak można by oczekiwać (na gcc 4.5).

Ale mam złe przeczucie, że to właśnie ze względu na mój kompilator robi "Optymalizacja wartości zwrotu" (RTO) na "auto os = test()". Rzeczywiście, jeśli modyfikować na następujące kwestie:

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

już nie dostać zarówno Test1 i test2 na wyjściu.

Chodzi o to, że "test" w klasie nie podlega kopiowaniu, więc nie ma szans na powielenie go. Po prostu chcę móc go zwrócić z funkcji. I wydaje się, że mogę to zrobić z GCC.

Wolałbym nie mieć inteligentnych wskaźników dereferencji do przydzielonego sterty lub ponownego otwarcia pliku, ponieważ obecnie działa bez robienia tych rzeczy. Po prostu mam wrażenie, że jestem trochę "niestandardowy" w moim podejściu, więc standardowy sposób robienia tego, co opisałem, będzie świetny.

Odpowiedz

15

mam zamiar odpowiedzieć na moje własne pytanie tutaj:

Na stronie GCC C++0x Library Features, spojrzeć na pozycji 27,9, który brzmi:

27.9 - strumienie opartych na plikach - Częściowa - Brakujące Operacje przenoszenia i wymiany

Prawdopodobnie jest to problem, który mam z gcc.

+0

Tak, to by to zrobiło. Dobre znalezisko. – GManNickG

+0

Nadal prawda? –

+0

Wygląda na to, że nie. Jeśli możesz, możesz edytować pytanie i odpowiedź. – Clinton

2

Problem jest z tym:

test(test&& old) {}; 

To pozwala skonstruować nowy test z rvalue test tak, ale nie mówi nic o swojej bazy, która jest po prostu są domyślne zbudowane (bez otwartego pliku) . Co chcesz to:

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

Który będzie przenieść strumień z old do bazy.

+0

Twoja odpowiedź podaje następujący błąd kompilacji w gcc 4.5: "" std :: ios_base :: ios_base (const std :: ios_base &) "jest prywatne". Czy na pewno masz to skompilować, a jeśli tak, to na jakim kompilatorze? – Clinton

+0

@ Clinton: Nie próbowałem kompilować kodu, chociaż robiłem to już wiele razy. (Uwaga: "kompiluje" niekoniecznie oznacza, że ​​jest poprawny C++). Powinieneś edytować swoje pytanie, dołączając nowy kod, który próbujesz i wszystkie błędy. – GManNickG

+0

Czy jesteś pewien, że funkcjastream ma konstruktor rvalue? – Clinton

0

Czy osoba dzwoniąca musi wiedzieć, że zwracana jest wartość ofstream, czy też bardziej sensowne byłoby zwrócenie numeru streambuf i umożliwienie wywołującemu zawinięcie go do strumienia?