File wrapper class in C++ (2)
Last time I showed how to implement a File
class. In the solution Brian (pictured on the right) and me used a second class as a wrapper around a standard FILE
pointer. The two classes worked together by means of a shared_ptr
. The shared_ptr
ensured that the file would not be closed until there were no more references to the file wrapper object. Reread the last post to see what I’m talking about.
A reader of this blog pointed out that there is another solution, one that turns out far more idiomatic. The constructor of shared_ptr
accepts an instance of a functor, named a Deleter. This functor will be called when the reference count drops to zero, and the object will be destructed. The resulting code looks like this:
#include <cstdio>
#include <tr1/memory>
class File {
public:
// conversion constructor
File(FILE *f) : stream_(std::tr1::shared_ptr<FILE>(f,
FileDeleter() )) { }
// copy constructor copies the shared_ptr
File(const File& f) : stream_(f.stream_) { }
private:
std::tr1::shared_ptr<FILE> stream_;
// local functor closes the FILE upon destruction
class FileDeleter {
public:
void operator()(FILE *f) const {
if (f != NULL)
std::fclose(f);
}
};
};
Right here I inlined the FileDeleter
class. You may also choose to put it outside the enclosing class, or it can even be implemented as a struct with operator()()
.
All in all, this solution is more elegant and more idiomatic than the previous one.