We're starting with this code: defer->void { CoUninitialize(); };
Using the macros in the second linked file, this expands to: auto _defer_instance_1234 = Defer{} % [&]()->void { CoUninitialize(); };
* The 1234 is whatever the line number is, which makes the variable name unique.* auto means infer the type of this local variable from the expression after the =. * Defer{} means default construct a Defer instance. Defer is an empty type, but it allows the % following it to call a specific function because... * Defer has an overloaded operator%. It's a template function, which takes a callable object (type is the template parameter Callable) and returns a DeferHolder<Callable> instance. * [&]()->void { /*code here*/ }; is C++ syntax for a lambda function that captures any variables it uses by address (that's the [&] bit), takes no parameters (that's the () bit) and returns nothing (that's the ->void bit). The code goes in braces. * DeferHolder calls the function it holds when it is destroyed. It's subjective but some (including me!) would say it's cursed because it's using a macro to make something that almost looks like C++ syntax but isn't quite. I'm pretty confident with C++ but I had no idea what was going on at first (except, "surely this is using macros somehow ... right?"). [Edit: After some thought, I think the most confusing aspect is that defer->void looks like a method call through an object pointer rather than a trailing return type.] I'd say it would be better to just be honest about its macroness, and also just do the extra typing of the [&] each time so the syntax of the lambda is all together. (You could then also simplify the implementation.) You end up with something like this: DEFER([&]()->void { CoUninitialize(); });
Or if you go all in with no args lambda, you could shorten it to: DEFER({ CoUninitialize(); });
|