Hacker News new | past | comments | ask | show | jobs | submit login

There's plenty of one-time cases where you don't want to declare an entire class but still enjoy scope-based functions. However, the approach in the post is not very C++-esque, I like this one much more: https://github.com/mawww/kakoune/blob/master/src/utils.hh#L5...



std::unique_ptr has a widely unknown second template argument called deleter. It is designed exactly for this purpose. You just do roughly like this(written from a phone):

    typedef fdwrapper = unique_ptr<int, close>;
    fdwrapper fdhandle(open(filename));


The only time I can think of where this is useful is when you are trying to be super defensive with possible exceptions being thrown.

Otherwise it seems a lot like you can just make the call at the end of scope yourself for the same line count and _much_ more readable code.

I guess if you have multiple return paths it's more tenable to use scoped dtors for this but it all really seems questionable to me -- I can't think of a single use-case where it'd be preferable to use something like this rather than a dedicated class.


> The only time I can think of where this is useful is when you are trying to be super defensive with possible exceptions being thrown.

If your application uses exceptions at all, then the time to be super-defensive about exceptions is all the time. If you don't form the habit, then you'll forget in the cases where it matters.

Plus, most programmers are pretty bad at identifying where exceptions might be thrown, because it tends to reduce to the question: "Where will my code have bugs?" Obviously, if you knew, you'd have fixed them...

> _much_ more readable code.

I'd argue that it's more readable to put state build-up and tear-down next to each other, so that future readers can see and modify them together. If you put them far apart, it's easier for them to skew.


It allows you to keep the cleanup next to the allocation/initialization, which is a nice organization. It's easy to ensure you haven't forgotten to clean something up in any exit path.

(Obviously, classic RAII has pretty much the same benefit. But it requires a whole class per type, whereas this approach has less boilerplate.)


It's rare that there is no chance of exceptions being thrown anywhere in a function, especially in the futurer as the code changes.. But even if you're really sure, it's so idiomatic to do cleanup in a destructor in C++ that it looks wrong to leave some cleanup code at the end of a function. Plus, it means you can think about cleanup at the same time you're thinking about creation, then forget about it later; one less thing to think about during the lifetime of the function.

I think life is simpler if you just adopt a blanket rule: all cleanup is done in destructors/scoped guards. Occasionally code might be slightly longer than it needs to be, but your life is simpler overall. Plus you can forget the old C rule of only one return from a function that you mentioned. (If you use exceptions anywhere then you already stopped using that rule anyway.)


You can use it for locks where std::lock_guard isn’t what you need, put the mutex.unlock in the scope_guard




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: