C++ elegance?

Wednesday, November 8, 2017

Still not feeling in top shape, but markedly better.

build

Christophe made a few comments about things that don't work well in build, so I spent a little bit of time addressing that, notably making sure that the way to build shared libraries works on macOS, Linux and Windows the same way.

Also added some conveniences to the default makefiles, like building with make V=1 or make DESTDIR=/tmp/foo install, things that developers using automake are used to. He suggested I add a .pc file to the recorder as well. But the recorder now is broken on MinGW due to the lack of <regex.h> there, I need to address that as well.

Mail and reviews

More code reviews are piling up.

The mail replication on f25-turbo is still not done with the copy of my various IMAP inboxes. I wish I could copy the files over from another local machine, but it looks like offlineimap embeds the name of the machine in the file name, so it does not seem to work.

C++: Ugly or Beautiful?

Frediano submitted a patch where he uses this defer macro (inspired by this StackOverflow post) taking advantage of some of the "recent" features in C++ combined with the most ancient C preprocessor hacks. I don't know if I find this elegant or perfectly ugly:

#ifndef defer
template <class F> struct deferrer
{
    F f;
    ~deferrer() { f(); }
};
struct defer_dummy {};
template <class F> inline deferrer<F> operator*(defer_dummy, F f)
{
    return {f};
}
#define DFRCAT_(LINE) _defer##LINE
#define DFRCAT(LINE) DFRCAT_(LINE)
#define defer auto DFRCAT(__LINE__) = defer_dummy{} *[&]() -> void
#endif

The usage for this is to replace something like this:

int foo()
{
    int rc = SUCCESS;
    int fd = open(...);
    if (some_complex_condition())
    {
        rc = FAILURE;
        goto error;
    }
    if (some_other_complex_condition())
    {
        rc = FAILURE;
        goto error;
    }
    do_something_that_matters()

error: close(fd); return rc; }

with the more elegant:

int foo()
{
    int fd = open(...);
    defer
    {
        close(fd);
    }; // Don't forget that semi-colon 

    if (some_complex_condition())
        return FAILURE;
    if (some_other_complex_condition())
        return FAILURE;

    do_something_that_matters()
    return SUCCESS;
}

So the end result is elegant. But the macro itself...