Boost logo

Boost :

From: Douglas Paul Gregor (gregod_at_[hidden])
Date: 2002-03-25 14:56:51


On Mon, 25 Mar 2002, David Abrahams wrote:
>
> ----- Original Message -----
> From: "Douglas Gregor" <gregod_at_[hidden]>
> >
> > Note a few important things: there is no instantiation stack
>
> When debugging metaprograms, some sort of instantiation stack is often
> the only thing that saves me.

Without this extension, I agree completely. I tend to put in bogus
instantiations to try to get printf-like functionality (typedef typename
i_want_to_see_this_type<T>::foo foo).

The extension gives printf functionality to metaprograms, so instead of
relying only on instantiation stacks to debug, you can craft your own
output to watch what is happening.

> IMO, the way to deal with that particular issue is:
>
> 1. Start with the deepest part of the stack (where the error occurred)
> first
> 2. Show the shallowest part of the stack next
> 3. Show the rest of the stack last
> 4. Use some kind of "error folding" in the editor/IDE so most of the
> stack is invisible until you click on a widget (or equivalent).
>
> OTOH, it might make sense for your error mechanism to be able to cut off
> instantiation details deeper than a certain level.
>
> -Dave

Suppressing part of the instantiation stack is only an option, and can be
turned off (i.e., suppressing 0 levels means "don't suppress anything").
The reason for suppressing part of the instantiation stack is that within
generic libraries there tend to be many levels of indirection. These
levels are hidden on normal use, and are generally undocumented, but they
come out of hiding to confuse the user whenever there is a syntactic
error.

Look back at the ugly Boost.Function error message I posted. The user's
error was to give Boost.Function an incompatible target object by calling
function<...>::operator= with inappropriate arguments. But the compiler
tells the user to look at the boost::function constructor, the
boost::function1 constructor, two private, undocumented assign_to methods,
and the function_invoker1 function from a 'detail' namespace. The actual
error message points somewhere in boost/function/function_template.hpp,
and not at the user's incorrect code. Suppressing the instantiation stack
keeps all of these indirection details hidden, and shows the error where
the error was made - in the call to operator=. If GCC has source-based
error information like the EDG compiler does, we could point to the '='
and state that the given function object is not compatible with the
Boost.Function object.

My summary: instantiation stacks are fine if they are yours, bad if they
are someone else's. If I am writing a library and a testcase fails, I want
to see all of the information. If I'm using a library I trust and I make a
mistake, I want to know where _my_ mistake is, not how the library is
implemented.

        Doug


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