2011-01-28 32 views
7

Tôi nghĩ rằng tôi sẽ nhận được ngay vào nó và bắt đầu với mã:Làm thế nào để trả lại một 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"; 
} 

Về cơ bản, tôi cần phải trả lại một ofstream. Tất nhiên bạn không thể sao chép một dòng, do đó, tôi không quan tâm đến mã trong bài kiểm tra lớp, và tôi đã biên dịch ở trên để biên dịch và làm việc như bạn mong đợi (trên gcc 4.5).

Nhưng tôi có cảm giác xấu đây chỉ là do trình biên dịch của tôi thực hiện "Tối ưu hóa giá trị trả về" (RTO) trên "auto os = test()". Thật vậy, nếu sửa đổi các điều sau:

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

Tôi không còn nhận được cả Test1 và Test2 ở đầu ra nữa.

Vấn đề là lớp "kiểm tra" không thể sao chép được, vì vậy không có cơ hội nào của dòng được sao chép. Tôi chỉ muốn có thể trả lại từ một hàm. Và tôi dường như có thể làm điều đó với GCC.

Tôi không muốn có con trỏ thông minh dereference cho một đống phân bổ của dòng, hoặc mở lại tệp, vì nó hiện đang hoạt động mà không làm những việc đó. Tôi chỉ có một cảm giác tôi là một chút "phi tiêu chuẩn" trong cách tiếp cận của tôi, vì vậy một cách tiêu chuẩn để làm những gì tôi đã mô tả sẽ là tuyệt vời.

Trả lời

15

Tôi sẽ trả lời câu hỏi của riêng tôi ở đây:

Trong trang GCC C++0x Library Features, có một cái nhìn tại mục 27.9, mà đọc:

27,9 - suối tập tin dựa trên phần - - Thiếu các hoạt động di chuyển và hoán đổi

Tôi đoán đó có thể là vấn đề tôi gặp phải với gcc.

+0

Vâng, điều đó sẽ làm được. Tốt tìm thấy, mặc dù. – GManNickG

+0

Vẫn còn đúng? –

+0

Không giống như không. Vui lòng chỉnh sửa câu hỏi và câu trả lời nếu bạn có thể. – Clinton

2

Vấn đề là với điều này:

test(test&& old) {}; 

này cho phép bạn xây dựng một mới test từ một rvalue test, vâng, nhưng nó nói gì về cơ sở của bạn, mà chỉ đơn giản là được mặc định xây dựng (không có tập tin mở) . Những gì bạn muốn là:

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

Điều này sẽ di chuyển luồng từ old vào cơ sở.

+0

Câu trả lời của bạn cung cấp lỗi biên dịch sau trên gcc 4.5: "'std :: ios_base :: ios_base (const std :: ios_base &)' là riêng tư". Bạn có chắc là bạn đã biên dịch, và nếu có, trên trình biên dịch gì? – Clinton

+0

@Clinton: Tôi chưa thử biên dịch mã của bạn, mặc dù tôi đã làm điều này nhiều lần trước đây. (Lưu ý "nó biên dịch" không nhất thiết phải kiểm tra cho nó là đúng C + +). Bạn nên chỉnh sửa câu hỏi của mình để bao gồm mã mới mà bạn đang thử và tất cả các lỗi. – GManNickG

+0

Bạn có chắc chắn ofstream có một hàm tạo rvalue không? – Clinton

0

Người gọi có cần biết rằng bạn đang quay trở lại ofstream hoặc có ý nghĩa hơn khi trả lại streambuf và để người gọi quấn nó trong luồng không?

Các vấn đề liên quan