WTB: Finally Keyword

March 28th, 2007

A little while ago I wrote about my hatred of some of C++’s features. This time I’m going to add to it with a bit of praise for C++, and then some more hate. Alright, lot more hate.

Basically, it all comes down to the RAII thing much of C++’s robustness is built around. In most cases it’s nice. Really nice. To use, that is. It’s very handy to just know that when an object goes out of scope (however that may happen) it will be properly destroyed - along with anything it manages. Isn’t that neat?

Well of course! And then again no.

The irritating bit is this: every C++ compiler must be able to generate code that mimics the try-finally construct used in other languages - yet, despite having try, it has no finally keyword. The typical response to this is that “C++ doesn’t need finally since it already has object destructors - finally would be redundant”, which strikes me as completely stupid.

Suppose I’ve got a C API that’s used in one little function, somewhere in the bowels of my application. This API has some simple rules: if begin_widget() succeeds, I need to call end_widget(), and if alloc_widget_bits() succeeds I need to call free_widget_bits() on its return value. In a language that includes a finally keyword that looks something like this:

void UseCrazyCApi( void )
{
    if( !begin_widget() )
        throw error();

    try
    {

        //call stuff that might throw

        widget_bits_t *bits = alloc_widget_bits();
        if( !bits )
            throw error();

        try
        {
            //do stuff with bits, some of which might throw
        }
        finally
        {
            free_widget_bits( bits );
        }
    }
    finally
    {
        end_widget();
    }
}

No, it’s not very pretty but it’s the only place this particular API is used. The only way to write this in C++, however, is to either munge things up with try-catch (which is even worse), or to do it “properly” with a resource-managing object, er, objects:

class WidgetBlock
{
public:
    WidgetBlock( void )
    {
        if( !begin_widget() )
            throw error();
    }

    ~WidgetBlock( void )
    {
        end_widget();
    }
};

class WidgetBits
{
public:
    WidgetBits( void )
    {
        bits = alloc_widget_bits();
        if( !bits )
            throw error();      
    }

    ~WidgetBits( void )
    {
        free_widget_bits( bits );
    }

    widget_bits_t* operator -> ( void )
    {
        return bits;
    }

    //this or should I allow implicit conversion? hrm…
    widget_bits_t* raw_ptr( void )
    {
        return bits;
    }

private:
    widget_bits_t *bits;    
};

void UseCrazyCApi( void )
{
    WidgetBlock the_block;

    //call stuff that might throw
    WidgetBits bits;

    //do stuff with bits, some of which might throw
}

There’s a massive list of things that irritate me about this code:

  • I had to define and create objects when what I really wanted to say is “always call this code”.

  • The name WidgetBlock, and the name of every instance thereof, both of which are completely useless (since a WidgetBlock has no purpose except to exist over a given code block), yet neither of which can be omitted.

  • WidgetBlock and WidgetBits aren’t really complete resource management classes. They lack proper copy constructors, assignment operators, and possibly a private operator new (if it doesn’t make sense to allow them on the heap - though making operator new private is more of a hint than a guarantee in this case, as someone can always embed the object in something that can go on the heap).

    Of course, it doesn’t make sense to create full-blown resource wrappers for use in a single function - but now that they exist the temptation to use them somewhere else in an unsafe manner also exists. So I either have to trust myself (and my colleagues) to know better (and to remember to know better), or I have to write even more code to hide these away in some god-forsaken class/namespace where (I hope) no one will ever look. And then there’d be the big “Here be Dragons” comment too.

    And then again it just feels wrong to have half-written resource wrappers.

  • It’s long and it obscures what’s going on.

    If I were working with something like shared_ptr< T >, which is used everywhere and is as idiomatic as plain old T*, then the resource wrapper would actually improve readability. But this is the only place this code is used. So every time I go through this code I’m likely to ask myself the same questions (like “OK, WidgetBlock does the begin_widget thing…did I make it throw if begin_widget fails?”), and each time I’m going to have to scroll through half a page of class definitions to find the answer.

  • Debugging operations on the bits variable is going to be annoying. Now that it’s in a wrapper class and the only way to get at it is via function (either operator -> or raw_ptr) I end up stepping into those functions any time I hit F11 on a line that tries to dereference or otherwise get at the pointer.

Now, if I were using this API all over the place, yes, it would make sense to create, debug, and use a set of resource management classes like those above. Templates might even take care of some of the work (depending on how similar the various parts of this API are) and it would be far less bug-prone to work with. But the point is that this isn’t the case here (or in many other bits of code).

Granted, this isn’t representative of most C++ code, but it does happen. And this is one case where the language imposes a rather severe limitation on how code can be structured (something it strives to avoid almost everywhere else).

</rant>

Sorry, comments are closed for this article.