Boost logo

Boost :

From: John Torjo (john_at_[hidden])
Date: 2003-04-24 08:48:15


Of course, after a little thinking ;-) :

Insted op applying the op_ macro to each operator,
The op_ macro could be applied to the variable itself, since when an
assertion would fail,
knowing the values each of the variables involved in the assertion
should be enough.

In other words, we can apply a macro only the first time
a variable is used (since at the following appearences of ***THE SAME***
variable will have the same value (I'm relying on this, since you should
definitely not use any operators that modify the initial value of a variable
within an assertion).

This way, the tested expression will be pretty readable.

So:
assert( (i == j) || (k < 0) ) would change into :
SMART_ASSERT( (v_(i) == v_(j)) || (v_(k) < 0) );

assert( (i < j) || (i == 0) || (j == 1) ); would change into
SMART_ASSERT( (v_(i) < v_(j)) || (i == 0) || (j == 1) );

The output of the above (in case the assertion fails) can look like:

Assertion failed:
'(v_(i) < v_(j)) || (i < 0) || (v_(k) == -1)'
i= '3'
j= '2'
k= '1'

Here's the new code:

---------------------------------------------
#include <assert.h>
#include <sstream>
#include <iostream>
#include <set>

// keeps multiple expressions
struct multiple_expr_keeper
{
    void add( const char * str)
    { m_collExprs.insert( str); }

    bool has( const char * str) const
    { return m_collExprs.find( str) != m_collExprs.end(); }
private:
    std::set< std::string> m_collExprs;
};

template< class type> inline const type & expr_keeper( const type & val,
const char * str, std::stringstream & out, multiple_expr_keeper &keeper)
{
    if ( !keeper.has( str))
    {
        out << str << "= '" << val << "'\n";
        keeper.add( str);
    }
    return val;
}

#define v_(x) expr_keeper((x), #x, out_str, the_keeper)

#define SMART_ASSERT(x) do { \
    std::stringstream out_str; \
    multiple_expr_keeper the_keeper; \
    if ( !(x)) std::cout << "Assertion failed: \n'" << #x << "'\n" <<
out_str.str() << std::endl; \
    } while(0)

int main()
{
    int i, j, k;
    k = 1;
    i = 3;
    j = 2;
    SMART_ASSERT( (v_(i) < v_(j)) || (i == 0) || (j == 1) );
    SMART_ASSERT( (v_(i) < v_(j)) || (i < 0) || (v_(k) == -1) );

    std::cin.get();
    return 0;
}

---------------------------------------------

--
John Torjo
-- "Practical C++" column writer for builder.com.com
Freelancer, C++ consultant
mailto:john_at_[hidden]

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