C++ Weekly - Ep 150 - C++20's Lambdas For Resource Management

preview_player
Показать описание
☟☟ Awesome T-Shirts! Sponsors! Books! ☟☟

T-SHIRTS AVAILABLE!

WANT MORE JASON?

SUPPORT THE CHANNEL

GET INVOLVED

JASON'S BOOKS

► C++23 Best Practices

► C++ Best Practices

JASON'S PUZZLE BOOKS

► Object Lifetime Puzzlers Book 1

► Object Lifetime Puzzlers Book 2

► Object Lifetime Puzzlers Book 3

► Copy and Reference Puzzlers Book 1

► Copy and Reference Puzzlers Book 2

► Copy and Reference Puzzlers Book 3

► OpCode Puzzlers Book 1


RECOMMENDED BOOKS

AWESOME PROJECTS

O'Reilly VIDEOS

Рекомендации по теме
Комментарии
Автор

I've fallen in love with your channel! Thank you 1000 times!

MightyMoveSemantics
Автор

Thanks. Another option, that works only with stateless lambdas (which is the case most of the time for a custom deleter), is to use a function pointer as the type for the lambda and then pass the lambda as a call argument, e.g.:

std::unique_ptr<FILE, void (*)(FILE*)> fileResource(fopen("file.txt", "r"), [](FILE* f){ fclose(f); });

I remember using this one-liner RAII many times before C++2a

michaeljabbour
Автор

That is really nice. Now I just need to convince the software standard board at my employer that we shouldn't switch to C++14, or 17, but 20 :D

giantnanomachine
Автор

Couldn't you use a deduction guide to move all that stuff to the constructor arguments? Having a lambda declaration as a template parameter is weird and confusing.

Omnifarious
Автор

Why is using a lambda deleter better than wrapping the File* with a class that has an old school constructor and destructor? It seems more clear and consistent to me than copy/pasting this lambda code whenever you want to safely use a file pointer? I am not a expert in this area, just trying to explore best practices.

ryanrapp
Автор

The emphasis is that the lambdas are stateless. If there are captured values/references, then you fallback on the first method.

Lojdika
Автор

Using C++17's user deduction guides, one can just write:
std::unique_ptr file{fopen("bla"), &fclose};
Nice and easy..
Deduction guides:
template<class T, class D >
unique_ptr(T*, D*) -> unique_ptr<T, D>;

workasm
Автор

I've always used a function template for that:
auto file = pack_unique(fopen("somefile.txt", "w"), [](FILE* f){ fclose(f); });

AxelStrem
Автор

This feels really odd. The unique_ptr is templatized on the *type* of the lamba that closes the file, but the lambda *value* hasn't been passed to unique_ptr's constructor. Why does it pick up the value of the deleter from the type? While this works and is useful, it feels like an bug in the language or library spec... I'd much prefer to see this work by specifying fewer template parameters, or "auto" in the template parameter list (so the type of the template parameter is derived from the lambda value passed to the constructor), and the lamba value being passed to the constructor.

StephenWarren
Автор

great video! maybe nix the bubble banner though. simple color banner would be more readable

petermitrano
Автор

Came back into C++ after being away for many years due advent of C++11 and I very quickly discovered this technique on my own. I was wanting a generic, use-it-on-the-fly RAII facility for adhoc resource management that would be comparable to Golang defer - this filled the bill rather closely. I went on to develop an 8000 line Java JNI program and this technique figured in hugely with managing JNI objects in precisely the adhoc manner that was needed. Ended up being a life saver for that particular project. The project remains production built under g++ 4.8.x so the code base continues to adhere to just the C++11 standard. It's totally builds under g++ 8.2.x and I do my development with that compiler - but the reason I've not moved forward from C++11 is another story.

TheSulross
Автор

I'm confused by the behavior of the final code; maybe my intuition about the type of a lambda is wrong? My intuition is that the type of a lambda is sort of equivalent to "a function that takes types X, Y, Z... and return type R". In the final code in this video, the decltype([](FILE* f){ fclose(f)) should return something that, in essence, would be "a function that takes a FILE* and returns nothing". But the fact that it is no longer necessary to pass the second argument (what used to be "deleter") seems to indicate that the type of a lambda is not just its signature, but also its content... in other words, what I would have expected the final code to look like, is something like this:

auto file = std::unique_ptr<FILE, decltype([](FILE*){})>( fopen("SomeFile.txt", "w"), [](FILE* f) { fclose(f); });

matthieud.
Автор

But wouldn't this crash if fopen returns null?

petermuller
welcome to shbcf.ru