$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: John Torjo (john_at_[hidden])
Date: 2003-05-02 02:32:05
> [from Samuel Krempp]
> But the same facility would be very useful for programmer errors too, as
> a way to state algorithm invariants with minimal overhead and
> comfortable formatting abilities, like a nice, extended, assert.
> BTW this is what the original thread was about, with John Torjo's
> SMART_ASSERT macro.
> (Of course, when a program fails an assertion, a core has all the
> information you can dream of. But I still like to get a good error
> message with the values of the interesting variables even before
> launching the debugger, as it is often enough to understand what is
> wrong. So I'm as intersted as John in a good way to enhance the basic
> assert macro)
Thanks. I'll try to provide a more detailed solution next week.
>
>
> In the context of a boost proposal of this Enforce thing, I think it
> would be good to simply provide 2 different macro names to address those
> 2 slightly distinct needs, e.g. ENFORCE and INVARIANT. (or THROWIF and
> ABORTIF, or whatever sounds self-explaining)
>
> of course both facilities would be very similar, but the distinguished
> names would stress the 2 different types of error checkings, and that
> seems to be an important point.
>
>
> In fac, with a suitable defintion of a
>
> struct DefaultAborter;
>
> inside which a throw(..) function prints a message and aborts, INVARIANT
> could simply be defined by :
>
> #define INVARIANT(exp) \
> *MakeEnforcer<DefaultPredicate, DefaultAborter>(\
> (exp), "Expression '" #exp "' failed in '" \
> __FILE__ "', line: " STRINGIZE(__LINE__))
>
>
> now we get an alternative to John Torjo's smart_assert :
>
> > assert( (i < j) || (i == 0) || (j == 1) ); would change into
> > SMART_ASSERT( (v_(i) < v_(j)) || (i == 0) || (j == 1) );
>
> INVARIANT( (i < j) || (i == 0) || (j == 1)) (i) (j) ;
>
This would look incredibly cool!
However, I spent some time, and I don't know how to implement it.
This is basically because (in my version),
when you say v_(i), it transparently does something like
log_information( i, #i); this is how it can actually output something like
'i = 5'.
However, just using (i) (j) I'm not sure we can do this. I may be wrong, but
this should not work:
#define OP1(x) std::cout << #x << "=" << (x) << std::endl;
#define OP2(x) std::cout << #x << "=" << (x) << std::endl; OP1
Then, the question is, will 'OP2(i)(j)' output the values of i and j?
By my reading of the standard, I think not. But I'm not sure.
The funny thing is that I tried the following example:
------------
#include <string>
#include <iostream>
#define OP1(x) std::cout << #x << "=" << (x) << std::endl;
#define OP2(x) std::cout << #x << "=" << (x) << std::endl; OP1
int main()
{
int i = 1, j =2;
OP2(i)(j);
std::cin.get();
}
------------
, and it works with VC6, gcc3.2 and it compiles with Comeau. So, it must be
ok.
In this case, I think somehow we can implement your suggestion with (i) (j).
It would be truly great!
Best,
John