
Ivan Sorokin <vanyacpp <at> gmail.com> writes:
On 12.09.2012 05:40, Andrew Sandoval wrote:
The first of these is RAIIFunction (I'm open to other names and coding conventions).
This approach has one problem.
The typical usage is something like that:
FILE* f = fopen(...); if (!f) return;
RAIIFunction<void> close_f = [f](){ fclose(f); } // may throw!!!
The construction of std::function for RAIIFunction may throw std::bad_alloc. In that case you will get leaked file handle.
Yes it could, but that is why I would always use the RAIIWrapper class for something as simple as fclose. e.g.: RAIIWrapper<RAIIDeleter(fclose)> pFile = fopen(...); if(!pFile.IsValid()) return; Because RAIIWrapper doesn't alloc anything, it will construct without risk of throwing. And because it has a built-in no-delete value, you don't need to check for NULL before letting it call fclose. It's a better solution for most things, but there are cases where RAIIFunction with a lambda or a function produced by bind are more desirably, and the user will need to understand the risks -- which in the large major of cases are next to nil anyway, before they elect to use RAIIFunction. (I'm not suggesting that an alloc failure isn't possible, I know it is, and I know that in a library you can't possibly anticipate all of the possible uses -- I am just suggesting that we have to deal with that kind of thing all of the time anyway. I don't know about you, but I use vector all of the time in place of malloc'd memory, because of it's RAII features, because it's expandable, etc. The risks are much the same. -Andrew Sandoval