[cppx] B true, or B thrown! (Using the >> throwing pattern)

How often have you declared a variable and invented an ungrokkable three-letter name for that variable, just to temporarily hold the result of some API function so that you can check it immediately after the call? Let me guess, you’ve done that thousands of times. And if so then here are happy tidings: you can completely avoid introducing all those helper variables! :-)

The conventional API function call.

The conventional pattern for a C++ API function call goes like …

  1. declare a result variable hr, say;
  2. initialize it with a call to some API function; and
  3. if hr, or whatever, denotes failure, then throw an exception.

For example,

File [oldfashioned_jam.cpp], complete source code:

#ifdef  _MSC_VER
#   define _CRT_SECURE_NO_WARNINGS      // Uh oh, wcstombs is, like, "deprecated"!
#   pragma warning( disable: 4428 )     // Oh my, universal-character-name encountered!
#endif

#include <iostream>
#include <stdexcept>
#include <vector>
#include <stdlib.h>     // wcstombs, EXIT_SUCCESS, EXIT_FAILURE
#include <stddef.h>     // ptrdiff_t
#include <locale.h>     // setlocale

typedef ptrdiff_t       Size;

void throwX( char const s[] ) { throw std::runtime_error( s ); }

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    if( nBytes < 0 )
    {
        throwX( "wcstombs failed to deduce buffer size" );
    }

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    Size const nBytesWritten = wcstombs( &buf[0], s, bufSize );
    if( nBytesWritten < 0 )
    {
        throwX( "wcstombs failed to convert string" );
    }

    return (stream << &buf[0]);
}

int main()
{
    setlocale( LC_ALL, "" );
    try
    {
        std::cout << L"" << std::endl;
        std::cout << L"Blåbærsyltetøy er godt!" << std::endl;
        std::cout << L"Blueberry \u03C0! \u263A" << std::endl;
        return EXIT_SUCCESS;
    }
    catch( std::exception const& x )
    {
        std::cerr << "!" << x.what() << std::endl;
    }
    return EXIT_FAILURE;
}

By the way, to compile this with MinGW g++ in Windows you need to either save the source code with UTF-8 encoding and no BOM, or replace each non-ASCII character with its Unicode escape.

Also note that the last output string intentionally contains a character, the \u263A smiley “”, that causes wcstombs to fail in Windows.

This code works, in the sense of detecting failures correctly, but the technique litters the code with result variables and if’s, which makes the code far less than clear. Wrapping each API function in a throwing C++ function might be the ideal solution. But for any typical API there are far too many API functions!

Don’t contemplate failure – assert success!

As a first step on the ladder to Thrower’s Heaven™, those if’s are easy to get rid of. Instead of saying, if this failed, throw!, simply say this succeeded, or else throw!. The or else is, of course, C++’s short-circuit || OR operator.

I can imagine that consultants love this notion of just asserting success rather than checking for failure!

In file [perlish_jam.cpp]:

typedef ptrdiff_t       Size;

bool throwX( char const s[] ) { throw std::runtime_error( s ); }

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    (nBytes >= 0)
        || throwX( "wcstombs failed to deduce buffer size" );

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    Size const nBytesWritten = wcstombs( &buf[0], s, bufSize );
    (nBytesWritten >= 0)
        || throwX( "wcstombs failed to convert string" );

    return (stream << &buf[0]);
}

At first glance this might seem unorthodox. But it’s now very very clear where exceptions are thrown, and what the conditions are for continuing with normal case code. Also, the code is shorter. :-)

So, I prefer this version to the previous one, if no silly coding guideline forbids it.

Possible problem: to support || the result type for throwX is now bool, instead of just void. Happily the modern versions of g++ and MSVC are smart enough to not complain about a missing return. But more generally this is one conundrum that I don’t know a good answer to for C++98: one compiler may complain if the return is missing, because clearly this function should return a bool, while another compiler, or even the same compiler!, may complain if the return is present, because it can clearly never be executed… C++0x will provide an answer, marking the function as no-return. But C++0x is not here yet.

Transfer the blame! (Uh, result)

In the 1990’s I came up with the idea of using the C++ >> operator to transfer a function result to the exception throwing logic, said exception throwing logic embodied in some object.

This way one could avoid many of the extremely local result variables.

I used some complicated macro schemes to pick up file names and line numbers in the exception throwing. But after some years of that I realized that I’d never actually used that information, and it just complicated and uglyfied the code! So, in the cppx library I dispensed with the exception throwing object, and separated the concerns: the object that >> transfers the API function result value to is only responsible for checking whether that value fulfills a condition, and accordingly produces false or true, while the throwing can be accomplished by any bool-valued function or functor such as throwX.

That is, in the cppx library’ exception throwing support I combined my earlier idea of using >> and my later Perlish-like practice of using ||.

And this yields a very nice (IMO) separation of concerns, namely >> assertion and || throwing:

File [modern_jam.cpp], complete source code:

#include <progrock/cppx/exception/basic_throwing.h> // throwX, Accept
#include <progrock/cppx/primitive_types.h>          // Size
#include <iostream>
#include <vector>
#include <stdlib.h>     // wcstombs, EXIT_SUCCESS, EXIT_FAILURE
#include <locale.h>     // setlocale
using namespace progrock::cppx;

std::ostream& operator<<( std::ostream& stream, wchar_t const s[] )
{
    Size const  nBytes      = wcstombs( 0, s, 0 );
    (nBytes >= 0)
        || throwX( "wcstombs failed to deduce buffer size" );

    Size const              bufSize     = nBytes + 1;
    std::vector< char >     buf( bufSize );

    // The count of bytes written does not include terminating nullbyte.
    wcstombs( &buf[0], s, bufSize )
        >> Accept< IsNonNegative >()
        || throwX( "wcstombs failed to convert string" );

    return (stream << &buf[0]);
}

int main()
{
    setlocale( LC_ALL, "" );
    try
    {
        std::cout << L"Blåbærsyltetøy er godt!" << std::endl;
        std::cout << L"Blueberry \u03C0! \u263A" << std::endl;
        return EXIT_SUCCESS;
    }
    catch( std::exception const& x )
    {
        std::cerr << "!" << x.what() << std::endl;
    }
    return EXIT_FAILURE;
}

The purpose of the Accept template is to avoid having to provide a specialized operator>> for each new predicate, if one defines new ones.

For example, for Windows programming you might define a special HRESULT success predicate in terms of the Windows API’s SUCCEEEDED macro, instead of using cppx::IsNonNegative. And, for example, you might want to support Boost-like lamda expressions. Or you might want some more complicated success criteria.

Still, the operator>> is quite trivial… :-)

File [progrock/cppx/exception/basic_throwing.h], complete source code:

// Copyright (c) Alf P. Steinbach, 2010.
// #include <progrock/cppx/exception/basic_throwing.h>

#ifndef PROGROCK_CPPX_EXCEPTION_BASICTHROWING_H
#define PROGROCK_CPPX_EXCEPTION_BASICTHROWING_H
#include <progrock/cppx/devsupport/better_experience.h>

//-------------------------------- Dependencies:

#include    <progrock/cppx/exception/classes.h>
#include    <string>

//-------------------------------- Interface:

namespace progrock { namespace cppx {

    inline bool throwX( std::string const& s )
    {
        throw Failure( s );
    }

    template< class Predicate >
    struct Accept: Predicate
    {};

    template< class Type, class Predicate >
    inline bool operator>>( Type const& v, Accept< Predicate > const& isOK )
    {
        return isOK( v );
    }

    struct IsZero
    {
        template< class Type >
        bool operator()( Type const& v ) const  { return (v == 0); }
    };

    struct IsNonZero
    {
        template< class Type >
        bool operator()( Type const& v ) const  { return (v != 0); }
    };

    struct IsPositive
    {
        template< class Type >
        bool operator()( Type const& v ) const  { return (v > 0); }
    };

    struct IsNegative
    {
        template< class Type >
        bool operator()( Type const& v ) const  { return (v < 0); }
    };

    struct IsNonNegative
    {
        template< class Type >
        bool operator()( Type const& v ) const { return (v >= 0); }
    };

    struct IsMinusOne
    {
        template< class Type >
        bool operator()( Type const& v ) const { return (v == -1); }
    };

    struct IsNotMinusOne
    {
        template< class Type >
        bool operator()( Type const& v ) const { return (v != -1); }
    };

} }  // namespace progrock::cppx

#endif

Cheers, & enjoy – Alf

PS: Do feel free to comment. The cppx library is a Work In Progress, and chances are that you may have insights and ideas that I didn’t think of, and that are not well known. In a way this blog serves to communicate and generate ideas and practices, so discussion is very much welcome! :-)

About these ads

10 comments on “[cppx] B true, or B thrown! (Using the >> throwing pattern)

  1. It seems in the same aura as Andrei’s Enforce<> (but I don’t recall the details).

    Anyway, how does

        // The count of bytes written does not include terminating nullbyte.
        wcstombs( &buf[0], s, bufSize )
            >> Accept< IsNonNegative >()
            || throwX( "wcstombs failed to convert string" );
    

    differ from

        // The count of bytes written does not include terminating nullbyte.
        wcstombs( &buf[0], s, bufSize ) >= 0
            || throwX( "wcstombs failed to convert string" );
    

    (perhaps just that you don’t want to “hide” a statement inside a logical test?)

    PS:
      (I think I never make a post without a PS :-))

    I’m really curious about better_experience.h!

    • Essentially it’s a style issue, yes.

      With one recognizable way to express something that way can be easily recognized without even thinking, which I think :-) improves clarity.

      And in choosing between the ways, >> Accept can handle more cases than a simple comparison. For example, it can invoke the Windows SUCCEEDED macro, which checks bit 31. In the text above I suggested checking the sign instead, and that’s a common technique (or was a common technique), but it only works for signed type. Of course the function call can be used directly as an argument to SUCCEEDED, or whatever macro or boolean function. But then it’s much less readable, with the main call nested inside something instead of at top level of the code.

      Cheers, – Alf

  2. Reading this :
    //version 1
    (nBytes >= 0)
    || throwX( “wcstombs failed to deduce buffer size” );

    is harder then reading this :
    //version 2
    if( nBytes < 0 )
    {
    throwX( "wcstombs failed to deduce buffer size" );
    }

    because the first line of version 1 actually contains a hidden negation :
    "If nBytes is NOT greater or equal to zero, throw an exception"

    The 2nd version is easier to read :
    "if nBytes less then zero, throw an exception"

    The fact that is shorter doesn't buy you anything ( except few keystrokes ;) ), since it increases the maintenance costs. The code maintainer (if they are not used to that) will not be happy to decipher what you meant there.

    But I must agree, it is a nice trick. Looks elegant :)

  3. oh I just noticed something. This version :

    ( nBytes < 0 ) &&
    throwX( “wcstombs failed to deduce buffer size” );

    is logically simpler, but IMO more complicated to read then with the if statement

  4. What about using enums? It sorta feels like “masking” then:


    #include
    #include

    int file_read() { return -2; }

    enum Guard { NonNegative };

    template
    bool operator&(T i, Guard g) {
    switch (g) {
    case NonNegative: return (i >= 0);
    default: return true;
    }
    }

    int main() {
    file_read() & NonNegative || (throw std::runtime_error("Eek"), true);
    return 0;
    }

    • WordPress messed up your code (comment preview functionality would be nice!). I think your code was meant to look like this:

      #include <stdexcept>
      
      int file_read() { return -2; }
      
      enum Guard { NonNegative };
      
      template< class T >
      bool operator&(T i, Guard g) {
        switch (g) {
          case NonNegative: return (i >= 0);
          default: return true;
        }
      }
      
      int main() {
        file_read() & NonNegative || (throw std::runtime_error("Eek"), true);
        return 0;
      }
      

      For ease of customization I’d do that more like…

      #include <stdexcept>
      
      int file_read() { return -2; }
      
      enum NonNegative {};
      
      template< class T >
      bool operator&( T const& i, NonNegative ) {
        return (i >= 0);
      }
      
      int main() {
        file_read() & NonNegative()
          || (throw std::runtime_error("Eek"), true);
      }
      

      … where instead of having to extend the Guard type with a new value, a new predicate can be added simply by adding yet another enum type.

      One main change with your idea is the change of operator >>&. Offhand what struck me was that I was unsure of the operator precedence with &, but that should not matter when one gets used to a convention, and when one encounters it for the first time presumably one would look it up. However, as I see it the & operator signals a bitwise OR, very strongly, so it’s easy to misunderstand (not forcing the reader to check things): hm, OK, that’s a bitwise OR with the result of the NonNegative function…

      I guess each of us find different notations more natural. >> was, to my eyes, the least misleading I could come up with, over some years. And one reason for that is that we’re used to this operator being overloaded, and we’re familiar with its relative precedence.

      Cheers, – Alf

      • Hi Alf, thanks for formatting the code correctly. One thing I like about the single enum type is that it means only one function to write (just add cases when adding an enum). Though there’s probably gonna be some problems where tests don’t make sense for all types.

        As for the operator&, I was just experimenting. To me “&” suggests “filtering out” bad values. The “%” operator suggests the same thing (to me — in math we often use the term “modulo” to mean “remove”). I also thought about using operator| to suggest “piping” to a guard. As you said, it’s a bit subjective.

  5. Pingback: 2010 in review | Alf on programming (mostly C++)

  6. This is pretty cool. Might be worthwhile to assert within the >> function.

    How are you getting your code formatted btw? My blog could seriously use it.

  7. Pingback: The Basics: Clean Code, Error Checking, Exception Handling « MFC Tips

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s