Interface Versioning in C++ Video

Friends from Skills Matter has put video with lecture about Interface Versioning in C++ given by Steve Love last Thursday. The lecture was organised by London chapater of ACCU.

Generally, Steve addressed problems of the DLL Hell and ABI compatibility proposing a not-so-simple, but applicable and usable solution for number of most common problems. Along the video, slides are also available, so it should be easy to grasp the idea.

I’ve received copy of Steve’s code and I’m preparing a few more tests which I hope to describe in details and post here soon.

Preparing Quickbook for Boost.Geometry

Generic Geometry Library (GGL)I’ve just started writing Boost.Geometry (aka GGL) documentation in Quickbook. It is a lightweight format and parser being developed by Boost used to prepare technical documentation for software, mainly for for Boost C++ Libraries. Quickbook files (.qbk) are used as input for BoostDoc which in turn is an extension of DocBook.

Quickbook is a textual format, it feels quite similar to AsciiDoc or some sort of Wiki dialect but dedicated for documenting C++ programming. It is extremely easy to grasp while drinking a single short coffee.

Anyway, it seems it is going to be a quite a book after all elements of Boost.Geometry are documented. One of the challenge I’ve found is to collect all bits necessary to document C++ concepts defined by Boost.Geometry. Unfortunately, Doxygen is not an ideal tool for this purpose, so current version of the documentation lacks of some sections of concepts description. So, I have to dig the source code to find out formal definitions and details of valid expressions and semantics.

Another challenge related to concepts is to find best way to structure their documentation. I started to browse documentation of existing Boost libraries looking for examples and what I found is that there is no best example. Various libraries document concepts in very different way.

A concept is a set of requirements consisting of valid expressions, associated types, invariants, and complexity guarantees

David Abrahams, Generic Programming Techniques

For example, neatly Boost.Fusion documents concepts with Quickbook, though some elements seem to be omitted. Boost.Graph doesn’t document with Quickbook, looks good, but some details are missing to me, for instance, titles in headers of tables saying what is what is return type and pre-/post-condition for valid expressions, etc. Documentation of Boost.IOStreams concepts sound well. On the other hand, Boost.GIL is an example of why Doxygen should not be used to document concepts of a C++ library.

It looks to me the old good Standard Template Library Programmer’s Guide at SGI is still a best and most complete example of how C++ concepts should be documented.

Given these experiences, I started to think of a way to improve the way concepts are documented within Boost. I believe it would be a good idea to have predefined block for concept in Quickbook. Something along these lines:

[concepttype [Point Concept]
  [this is a concept for 0-dimensional geometry]
  [notation
    [term 1] [description 1]
  ]
  [refinement [concept 1] [concept 2]]
  [associated
    [type 1] [description 1]
  ]
  [expressions
    [name 1 [expr 1]
      [type requirement 1] [return type 1]
  ]
  [semantics
    [name 1 [expr 1]
      [precondition 1] [semantic 1] [postcondition 1]
  ]
  [complexity [...]]
  [invariants
    [invariant 1] [description 1]
  ]
  [models [model 1] [model 2]]
  [notes
    [ note 1] [ note 1]
  ]
  [seealso ...]
]

I posted my proposal to boost-docs list explaining the motivation in details. It’s an interesting experience of a C++ documentation craftsman, anyway. (BTW, Daniel James just announced Quickbook port to Spirit 2.)

Kitware Developer blog launched

CMake - cross-platform build systemA few minutes ago, Bill Hoffman from Kitware posted short message to the CMake project mailing list with an interesting announce:

Kitware launched its first developer blog today with contributions from Company technical and business leaders.

The CMake build system is one of the main category of topics on the Kitware blog, so I presume it may be of interest of OSGeo Community as the CMake build system is slowly winning over more and more folks here :-)

First CMake-related post is about Deploying on Windows with DLL Manifest Issue

Another interesting post on the blog is Will Schroeder‘s answer to the question Why Open Source Will Rule Scientific Computing? It’s really worth reading.

illegal token on right side of ‘::’

libLAS - ASPRS LiDAR data translation toolsetOne of libLAS users reported that when use of #include <liblas/lasreader.hpp> in his application compiled with Visual C++ 10.0 from Visual Studio 2010 cause this error:

utility.hpp(253): error C2589: '(' : illegal token on right side of '::'

The error is an incarnation of a very well-known problem in Visual C++ when using the C++ Standard Library elements, especially the Standard Template Library, in Windows API-based programs. As libLAS library does use the C++ library, so does a user’s application if includes libLAS headers.

The problem is caused by conflicting definitions of min() and max() macros defined in windef.h header. Macros in C++ are scope-less evil, especially if defined in public headers using such extremely unique names as min or max. The fact that Microsoft defined it way before C++ was born absolves them at large, but for the Spirit sake, they should learn the lesson and disable it for good in C++ mode (but not yet another MS-specific way!). No one who’s sane need or want to use them!

Pie in the sky. In the meantime, C++ programmers as the libLAS user who reported this problem have to deal with it on their own. The easiest way is to check CodeProject or Q143208 or search (not google) for solution like #define NOMINMAX for Visual C++ compiler.

However, is another option is to apply a simple trick to call of *::min() or *::max() functions (i.e. std::min() or std::max() which effectively prevents macro substitution, so the Visual C++ compiler (or any other compiler with similar problem) does not complain about illegal token. The trick is to wrap function name, fully qualified name, with parentheses:

(std::min)(x, y);

In most cases of use of C++ Standard Library as described above, it is required for the following functions:

(std::min)(x, y);
(std::max)(x, y);
(std::numeric_limits<T>::min)();
(std::numeric_limits<T>::max)();

In case a user-defined type has a member function with exactly the same name as a macro present in global scope (macros always live in global scope!), it may be necessary to apply the very same trick when a member function is called on an object:

template <typename T, int Size>
struct Series
{
  T min() { return *(std::min_element(s, s + Size); }
  T& operator[](int index) { return s[index]; }
private:
  T s[Size];
};

Series<int, 3> s;
s[0] = 2;
s[1] = 3;
s[2] = 1;

int m = (s.min)(); // long way, but here is the trick

There is one side effect which may be an inconvenience. This trick disables argument dependent name lookup (ADL, aka Koenig lookup).

Exceptions to error codes translation made simple

On many occasions, it is not possible or it’s even forbidden to let an exception thrown to sneak out of a function. On many occasions, it is necessary to sink all exceptions in place where they may occur and translate exceptions thrown to error codes. I have observed it’s not uncommon software projects stick to some rules about how they handle exceptions, like:

  • I’m sorry, I don’t like the fat & slow hippo RTTI (BTW, hippo can run 50 km/h!).
  • My function, class, library never ever throws exceptions.
  • I use exceptions to signal error conditions only from and within internal components, but never let them to cross the line drawn by public interfaces.
  • I write C wrapper for C++ library, I have to translate exceptions to error codes.
  • Exceptions? I have no idea who was mad enough to invent such a $%&@ beast. Forget!

Shortly, not for everyone exceptions are kosher, gluten and lactose-free meals.

Even if exceptions are not kosher, it is necessary to love & deal with them because…use of standard library elements or 3rd-party components which may throw, coding conventions ignorance within a team, just-in-case prevention, etc. Handling exceptions may make code very messy (check how Java camp deals database connection problems). It is possible to handle exceptions and maintain clean code.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Martin Fowler

Below is a simple example showing how to solve some of the problems pointed above. The basic idea is to implement one-for-all exceptions handler where all types of exceptions possible to be thrown are killed and translated to specified error code, exceptions have chance to send S.O.S. code before sinking.

#include <cassert>
#include <exception>
#include <iostream>
#include <stdexcept>

template <typename T>
inline T const& handle_exception(char const* const who, T const& rc)
{
    try
    {
        throw;
    }
    catch (int e)
    {
        std::cerr << who << " caught int: " << e << std::endl;
    }
    catch (char const* e)
    {
        std::cerr << who << " caught c-string: " << e << std::endl;
    }
    catch (std::exception const& e)
    {
        std::cerr << who << " caught std::exception: " << e.what() << std::endl;
    }
    return rc;
}

#define EXCEPTION_TRY() \
    try {

#define EXCEPTION_CATCH_AND_RETURN(success, failure) \
    } catch (...) { \
        return handle_exception(__FUNCTION__, failure); \
    } \
    return success;

// use it to exit void function on error
#define EXCEPTION_CATCH_AND_EXIT() \
    } catch (...) { handle_exception(__FUNCTION__, false); \
    return; }

template <typename T>
class number
{
public:
    // public ctor, may throw
    number(T value) : value_(value)
    {
        if (value != value)
            throw "value is NaN";
    }

    // public save division, never throws
    bool divide_s(double& result, T const& den) const
    {
        EXCEPTION_TRY()
        result = divide_(value_, den);
        EXCEPTION_CATCH_AND_RETURN(true, false)
    }

private:
    T value_;
    // used internally by private methods, allowed to throw
    double divide_(T const& num, T const& den) const
    {
        if (den > 0)
        {
            return num / den;
        }
        throw std::invalid_argument("denominator is zero");
    }
};

// C wrapper is not allowed to throw exceptions
double divide_numbers(double num, double den)
{
    EXCEPTION_TRY()

    number<double> n(num);
    double r = 0;
    n.divide_s(r, den);

    EXCEPTION_CATCH_AND_RETURN(true, false)
}

int main()
{
    bool success(false);
    double result(0);

    // Using C++ interface
    {
        number<int> n(10);
        // no error logged
        success = n.divide_s(result, 2);
        assert(success);
        // error logged, error code returned
        success = n.divide_s(result, 0);
        assert(!success);
    }
    // Using C interface
    {
        // no error logged
        result = divide_numbers(10, 2);
        // error logged
        result = divide_numbers(10, 0);
        // error logged
        float nan = 0;
        result = divide_numbers(nan / 0, 10);
    }
}

It’s simple and not ideal, but it did the job very well for myself and number libraries. Certainly, there are is a room for improvements. The logging mechanism is a simple one. It’s a good idea to add catch clauses for other types, even for int, especially if one has to deal with throw __LINE__; signals.

There is a lot of googlefindable articles and books one can buy. Here is the (incomplete) list of favourites guidelines:

Thanks to wonderful ACCU folks for a very interesting brainstorm on similar topic we had one day. Comments, improvements and bug reports would be greatly appreciated.