Skip to content
Haitao Zhang edited this page Sep 28, 2015 · 2 revisions

RAII

While RAII is a good idea it also exhibits a clear weakness. For example when you open a file with a ifstream or ofstream you want the stream object's RAII to automatically close the file when the stream object is destroyed. This creates the awkwardness that you can't pass these objects around as return values. The function that created the object on its stack will delete the object when the function exits which will in turn close the underlying file, which certainly is not what you expected if you want to pass it back to the caller (STL prevents this by deleting the copy constructor on these streams so you can't return them by accident). The alternatives are:

  1. Create the object on the heap and pass back the pointer. But now the caller (or someone else) has the responsibility to delete the stream object which defeats the purpose of RAII.

  2. Pass down a reference from the caller. And you need to send down reference from the outermost scope where you want the object to survive. You are now exposing details to top level functions.

Note istreams and ostreams are typically passed by reference and in general you don't delete them (or you may have an owner object like a session manager that manages the life cycle for them).

Sum type

With the file streams problem just mentioned often it is easier to pass around path objects that point to files instead of streams. But this creates another problem. Suppose you create a caching HTTP client. Some URLs (such as queries) you don't want to cache so you want to pass back an istream, which is likely (such as in Poco) owned by a session manager. Some URLs (such as downloads) you want to cache and return a path to the cached file (returning the file stream would be cumbersome as we have seen earlier). Now you have an interface issue. It would be a lot simpler and safer if I can just wrap a ML-like sum type over the resource, but instead I may have to roll my own tagged union type and remember to use it correctly. Instead of exposing the tagged union I would create a class wrapped around the union with a uniform accessor interface if possible. In the caching HTTP client the wrapper class may provide getter methods to send back a string of the content or copy to an ostream. But what if the consumer of the content wants an istream&? Now that the consumer is passed this object. Maybe we can use an unique_ptr to wrap around the ifstream in our accessor and return that instead.

Clone this wiki locally