Boost logo

Boost :

Subject: Re: [boost] [assert] static_assert envy
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2011-01-18 16:03:02


----- Original Message -----
From: "Thomas Klimpel" <Thomas.Klimpel_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Tuesday, January 18, 2011 9:31 PM
Subject: Re: [boost] [assert] static_assert envy

> Robert Kawulak wrote:
>> 2011/1/18 Thomas Klimpel wrote:
>> >> BOOST_ASSERT_IF_MSG( foo(), condition, "something is wrong" );
>> >
>> > I would prefer
>> > BOOST_ASSERT_MSG( !foo() || condition, "something is wrong" );
>> > so I don't need to think about the details of the differences between
>> BOOST_ASSERT_IF_MSG and BOOST_ASSERT.
>>
>> Then consider a simple example:
>> foo is: !c1.empty() && !c2.empty()
>> condition is: c1.front() ? c2.front() : def_val()
>>
>> Now you have to compute !foo || condition, which is simple, but: 1)
>> makes several opportunities for a mistake, 2) results in an expression
>> that may be harder to decipher than the two initial expressions. And
>> again, the resulting assert message can be nicer, too.
>
> Perhaps let's also consider my argument
> "so I don't need to think about the details of the differences between BOOST_ASSERT_IF_MSG and BOOST_ASSERT"
> in more detail:
>
> The macro is named 'BOOST_ASSERT_IF_MSG' and takes three arguments. The last argument is clearly the message, as is easy to see from the usage. But is the first argument the condition that is asserted true, or the precondition for the assertion to be true. From the position of ASSERT in the name of the macro, I would guess that the first argument is the condition that is asserted true. However, from the way I would write it as "normal code" (if (foo()) assert(condition);), and because the precondition should come before the condition, I would guess that the first argument is the precondition for the assertion to be true. So I have to dig into the details of BOOST_ASSERT_IF_MSG and BOOST_ASSERT to understand the code.
>
>
> So back to your argument, that "BOOST_ASSERT_IF(..., ...)" is more readable than "BOOST_ASSERT(!(...)||(...))". Yes, you are right, if (...) { ... } else { ... } is often more readable than cryptic exclamation marks, question marks, brackets, ampersands and vertical dashes. This a good argument in favor of a "design by contract" library as Lorenzo Caminiti has developed (I think Thorsten Ottosen has also done work in this direction). But implementing a partial language with macros for some special cases isn't such a great thing, because it would just be another language that I would have to learn. If you stick with the logic expressions on the other hand, the language is already well known.
>
>
> Conclusion for me: There is a difference whether you
>
> 'assert(condition && "text message ingeniously included into a Boolean expression exploiting missing type safety");'
>
> is not great or whether you say
>
> 'assert(!(precondition)||(condition));'
>
> is not great. What we see here is really just the Boolean expression that is asserted to be true. It's not as readable as it could be, but the alternative is a proliferation of similar macros with slightly different behavior.

If we want to evaluate a condition when BOOST_DISABLE_ASSERTS is not defined we could add a macro BOOST_WHEN that can be used like

BOOST_WHEN( !c1.empty() && !c2.empty()) {
    BOOST_ASSERT_MSG(c1.front() ? c2.front() : def_val(), "something is wrong" );
}

and defined as

#if defined(BOOST_DISABLE_ASSERTS)
# define BOOST_WHEN( CND) if(true) {} else
#else
# define BOOST_WHEN( CND) if(!(CND)) {} else
#endif

Compared to

BOOST_ASSERT((!( !c1.empty() && !c2.empty()) ||(c1.front() ? c2.front() : def_val())) && "something is wrong" );

is not shorter. It is just an alternative that avoids proliferation of similar macros and preserv readability.

Best,
Vicente


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