Boost logo

Boost :

Subject: Re: [boost] TMP error messages [ was Re: New libraries implementing C++11 features in C++03 ]
From: Ábel Sinkovics (abel_at_[hidden])
Date: 2011-11-26 08:22:32


Hi,

> The problem is that errors point to code that is deep within the library's
> implementation, or worse, the implementations of helper libraries used
> by the library. To understand the error, the user has to look at the
> library's implementation. The user shouldn't have to do that -
> understanding the implementation of a library should not be a
> prerequisite for using it.
>
> If you have any specific suggestions about what compilers could do to turn
> these errors from deep within the library implementation, into errors
> that do not require knowing anything about the library implementation,
> I would like to hear it, and I'm sure so would compiler writers.
>
> Otherwise, you have to accept that library writers face a trade-off
> between the user-friendliness of error messages, and the expressiveness,
> terseness, and power obtained by extensive use of advanced techniques
> such as template metaprogramming. There is no one right answer to
> this tradeoff, and it is good for users to have different alternatives
> available to them.

We've been experimenting with returning error messages from TMP
libraries that make sense in the domain of the library. Our approach is
returning a class describing the error when a metafunction is called
with invalid arguments (a pretty-printer can display that information
later in a human-readable way). The assumption is that this error
information is returned by a metafunction deeply inside the TMP library
and need to be propagated out (maybe changed a bit along the way to make
more sense to the user). For this we've used monads, using which we
could simulate exceptions being thrown at compile-time. Using monads
increases the complexity of the TMP library, however, most of it can be
hidden by another library. We've been working on such a library (not in
Boost).

What TMP library authors can do is wrapping the body of every
metafunction with a template that "adds" error propagation to it. For
example instead of:

template <class A, class B, class C>
struct some_metafunction_in_the_library :
   f<g<A, C>, h<B>, A>
{};

one can write

template <class A, class B, class C>
struct some_metafunction_in_the_library :
   try_<f<g<A, C>, h<B>, A> >
{};

in which case if f, g or h returns an error, the same error is returned
by some_metafunction_in_the_library instead of breaking the compilation
with a cryptic error message. At the top level it can be pretty-printed
by a test harness (eg. simple binary built to pretty-print it or by a
TMP unit testing framework). A downside of using it is that it makes
compilation slower (see
http://plcportal.inf.elte.hu/en/publications/TechnicalReports/monad-tr.pdf
for measurements).

So far we've only been using it for improving error messages coming from
template metafunctions. Cases where they can't be easily and clearly
separated from runtime code haven't been addressed yet.

This solution is part of a library implementing monads in C++ template
metaprogramming.
Documentation: http://abel.web.elte.hu/mpllibs/metamonad/index.html
Source code: https://github.com/sabel83/mpllibs/tree/master/libs/metamonad

Note that there are only a few examples so far.

Regards,
   Abel


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk