I think I'll get right into it and start with the code:
#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";
}
Basically, I need to return an ofstream. Of course you can't copy an ofstream, so I fiddled around with the code in the class test, and I got the above to compile and work as you would expect (on gcc 4.5).
But I have a bad feeling this is just due to my compiler doing "Return Value Optimization" (RTO) on "auto os = test()". Indeed, if modify to the following:
int main()
{
auto os = test("testfile");
os << "Test1\n";
auto os2开发者_StackOverflow = std::move(os);
os2 << "Test2\n";
}
I no longer get both Test1 and Test2 in the output.
The thing is, the class "test" isn't copyable, so there's no chance of the ofstream being duplicated. I just want to be able to return it from a function. And I seem to be able to do that with GCC.
I'd rather not have dereference smart pointers to a heap allocated ofstream, or reopen the file, as it currently works without doing those things. I just have a feeling I'm being a little "non-standard" in my approach, so a standard way of doing what I've described would be great.
I'm going to answer my own question here:
In the GCC C++0x Library Features page, have a look at item 27.9, which reads:
27.9 - File-based streams - Partial - Missing move and swap operations
I guess that's probably the issue I'm having with gcc.
The problem is with this:
test(test&& old) {};
This lets you construct a new test
from an rvalue test
, yes, but it says nothing about your base, which is simply being default constructed (no open file). What you want is this:
test(test&& old) : std::ofstream(std::move(old)) {};
Which will move the stream from old
into the base.
Does the caller need to know that you are returning an ofstream
, or would it make more sense to return a streambuf
, and let the caller wrap it inside a stream?
精彩评论