0

I need smart pointer-like behaviour - to execute arbitrary code when an object goes out of scope. Another example would be std::lock_guard that would call unlock() on a mutex object when it goes out of scope.

Is there any standard C++ classes that can do something like:

FILE *fp = fopen("foo.txt", "w");
...
DyingWish d( [&fp]() { fclose(fp); } );

//now when 'd' goes out of scope, fclose() will be called on fp

I found that std::unique_ptr accepts a custom deleter functor. So, I can do:

std::unique_ptr<void, std::function<void (void*)> d(nullptr, [&fp]() { fclose(fp); });

But unique_ptr will call invoke the deleter only if the pointer is not null. So I need to do a hack like:

std::unique_ptr<void, std::function<void (void*)> d((void*)1, [&fp]() { fclose(fp); });

OR

std::unique_ptr<void, std::function<void (void*)> d(nullptr, [&fp]() { fclose(fp); });
p.reset((void*)p);

The above code obviously is verbose, hackish and messy.

Is there any standard C++ class with which I can accomplish this (similar to the DyingWish use case above)? I would like to avoid writing a class for this. I am fine with a using declaration though.

I can do:

using DyingWish = std::unique_ptr<void, std::function<void (void*)>;

But that too requires the hack to avoid the null pointer problem, and also a useless first argument.

Syam
  • 163
  • 1
  • 8
  • you can create a local struct/class with that code in its destructor. – engf-010 Apr 28 '21 at 10:00
  • That'd require me to write a class definition inside the function and then create a local variable of that class. That's way too many lines than I'd prefer. I was hoping for a one-line solution like ```std::lock_guard```. – Syam Apr 28 '21 at 10:04
  • It's pretty implement yourself, here is an example for inspiration: [ScopeGuard.h](https://github.com/SerenityOS/serenity/blob/c841012f569dba4fa72e9eb8989bb847be4535bc/AK/ScopeGuard.h) – asynts Apr 28 '21 at 10:07
  • you can define a struct/class and a variable in one go : struct X { ... } x {}; – engf-010 Apr 28 '21 at 10:09
  • 1
    Boost has some ScopeExit solution. C++ experimental library as well, but I didn't find a way to use it with gcc. Better just write some `OnScopeExit` class yourself, it's quite straightforward. – pptaszni Apr 28 '21 at 10:09
  • Thanks for the suggestions. I know that writing my own class is trivial. I was just wondering if there's already something in the standard library, given how many new features have been introduced in recent years. I discovered the custom deleter feature of unique_ptr only during this process. – Syam Apr 28 '21 at 10:12
  • @pptaszni Thanks for introducing the term ScopeExit. Now I am finding resources on scope_guard and other implementations. – Syam Apr 28 '21 at 10:19
  • 2
    Relevant question: [What is ScopeGuard in C++?](https://stackoverflow.com/q/31365013/580083). Also, look at https://en.cppreference.com/w/cpp/experimental/scope_exit. It is not yet in C++, but likely will be in the future. Another relevant question: [Is there a C++ standard class to set a variable to a value at scope exit?](https://stackoverflow.com/q/36644263/580083). – Daniel Langr Apr 28 '21 at 10:22
  • Just one more comment: in my old code I used `shared_ptr` like this: `std::shared_ptr scopeGuard(nullptr, [&dataFile](void*) { dataFile.remove(); });` to remove the file on scope exit. Syntax is a bit easier than with `unique_ptr` because the deleter is type-erased. Note that lambda is not allowed to throw exceptions. – pptaszni Apr 30 '21 at 12:54

0 Answers0