When interacting with C APIs there is this common pattern:

foo *f;
init_foo(f);

int err = some_func(f);
if (err) {
  free_foo(f);
  return 1;
}

bar *b;
init_bar(b);

err = some_other_func(f, b);
if (err) {
  free_bar(f);
  free_foo(f);
  return 2;
}

// etc

free_bar(f);
free_foo(f);
return 0;

This is quite verbose and error-prone. It's easy to forget adding a cleanup function to one of the error branches when doing a refactor.

One way to make it a bit nicer is using goto.

foo *f = NULL;
bar *b = NULL;
int result = 0;

init_foo(f);
int err = some_func(f);
if (err) {
  result = 1;
  goto cleanup;
}

init_bar(b);

err = some_other_func(f, b);
if (err) {
  result = 2;
  goto cleanup;
}

// etc

cleanup:
if (b)
  free_bar(b);
if (f)
  free_foo(f);

return result;

But gotos can be uncomfortable.

In C++ one could also use unique_ptr to automate the cleanup calls using a custom deleter.

std::unique_ptr<foo *, decltype([](foo *f) { free_foo(f); })> f;
init_foo(f.get());

int err = some_func(f.get());
if (err) {
  return 1;
}

std::unique_ptr<bar *, decltype([](bar *b) { free_bar(b); })> b;
init_bar(b.get());

err = some_other_func(f.get(), b.get());
if (err) {
  return 2;
}

// etc

return 0;

That works, but what I really want to have in these situations is defer. Which is a way to defer execution until the end of the scope. Repeated defers work as a stack, the last one executes first, then the previous and so on. Same as the destructors.

// example
#include <iostream>

int main(int argc, char** argv) {
    defer({
        puts("defer 1");
        printf("argc = %d\n", argc);
        for (int i = 0; i < argc; ++i) {
            printf("\targv %d = %s\n", i, argv[i]);
        }
    });

    defer({ puts("defer 2"); });

    puts("hello");
}

Outputs:

hello
defer 2
defer 1
argc = 4
	argv 0 = /app/output.s
	argv 1 = foo
	argv 2 = bar
	argv 3 = baz

Building on unique_ptr it's actually fairly easy to implement a defer macro:

#ifndef defer
#include <memory>

#define CONCAT(x, y) x##y
#define DEFER_IMPL(expr, id)                                         \
    auto CONCAT(_defer_call, id) = [&](void*) expr;                  \
    std::unique_ptr<void, decltype(CONCAT(_defer_call, id))> CONCAT( \
        _defer_call_ptr_, id)((void*)1, CONCAT(_defer_call, id))

#define defer(expr) DEFER_IMPL(expr, __COUNTER__)
#endif

View on Compiler Explorer

The macro just creates a unique_ptr that has a deleter with a lambda that executes the given expression (expr.)

It evaluates to something like:

auto defer_call = [&](void*) {
    // expr
};
std::unique_ptr<void, decltype(defer_call)> defer_call_ptr ((void*)1, defer_call);

The actual value of the pointer does not matter to us, as it's never dereferenced. What's important is that it does not equal nullptr, otherwise the deleter is not called by unique_ptr, so I used the value 1.

One problem we have to overcome is multiple defers in the same scope. We need to use different variable names for them, otherwise the compiler will complain (rightfully so.)

This is where the __COUNTER__ macro comes in. __COUNTER__ evaluates to a number, starting at 0 and incrementing by 1 each time the macro is evaluated.

We can use this to create unique variable names for our defer implementation by concatenating a unique id with a prefix each time defer is called.

So the above example expands to

auto _defer_call0 = [&](void *) { /*defer 1*/ };
std ::unique_ptr<void, decltype(_defer_call0)> _defer_call_ptr_0((void *)1,
                                                                 _defer_call0);

auto _defer_call1 = [&](void *) { /*defer 2*/ };
std ::unique_ptr<void, decltype(_defer_call1)> _defer_call_ptr_1((void *)1,
                                                                 _defer_call1);
puts("hello");