View mode: basic / threaded / horizontal-split · Log in · Help
September 02, 2012
Trouble creating a formatted assert wrapper
One thing that's always bothered me is that I have to use 
std.string.format to produce useful assert messages:

assert(x == 1, format("x doesn't equal 1, it is %d", x));


Of course, I tried to solve this by producing my own assert-like 
function wrapper:

void myAssert(Args...)(lazy bool condition, lazy Args args)
{
    assert(condition, format(args));
}


That's all good, but the problem now is that I get the wrong file 
and line in the assert message, so I tried to use the default arg 
__FILE__ and __LINE__ trick:

void myAssert(Args...)(lazy bool condition, lazy Args args, int 
line = __LINE__, string file = __FILE__)
{
    if (!condition)
    {
        writeln("Assertion failed @ %s:%d", file, line);
        writefln(args);
        exit(1);
    }
}


But I can't have default arguments because of the variadic 
arguments!

Can anyone think of a way around this?
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sun, 02 Sep 2012 19:14:07 +0200, Peter Alexander  
<peter.alexander.au@gmail.com> wrote:

> One thing that's always bothered me is that I have to use  
> std.string.format to produce useful assert messages:
>
> assert(x == 1, format("x doesn't equal 1, it is %d", x));
>
>
> Of course, I tried to solve this by producing my own assert-like  
> function wrapper:
>
> void myAssert(Args...)(lazy bool condition, lazy Args args)
> {
>      assert(condition, format(args));
> }
>
>
> That's all good, but the problem now is that I get the wrong file and  
> line in the assert message, so I tried to use the default arg __FILE__  
> and __LINE__ trick:
>
> void myAssert(Args...)(lazy bool condition, lazy Args args, int line =  
> __LINE__, string file = __FILE__)
> {
>      if (!condition)
>      {
>          writeln("Assertion failed @ %s:%d", file, line);
>          writefln(args);
>          exit(1);
>      }
> }
>
>
> But I can't have default arguments because of the variadic arguments!
>
> Can anyone think of a way around this?

void myAssert(int line = __LINE__, string file = __FILE__, Args...)(lazy  
bool condition, lazy Args args) {
    if (!condition)
    {
        writefln("Assertion failed @ %s:%d", file, line);
        writefln(args);
        exit(1);
    }
}


-- 
Simen
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sunday, 2 September 2012 at 18:23:48 UTC, Simen Kjaeraas wrote:
> void myAssert(int line = __LINE__, string file = __FILE__, 
> Args...)(lazy bool condition, lazy Args args) {
>     if (!condition)
>     {
>         writefln("Assertion failed @ %s:%d", file, line);
>         writefln(args);
>         exit(1);
>     }
> }

Nice. I thought of that, but for some reason I thought that you 
couldn't have default args before variadic args.
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sun, 02 Sep 2012 20:46:50 +0200, Peter Alexander  
<peter.alexander.au@gmail.com> wrote:

> On Sunday, 2 September 2012 at 18:23:48 UTC, Simen Kjaeraas wrote:
>> void myAssert(int line = __LINE__, string file = __FILE__,  
>> Args...)(lazy bool condition, lazy Args args) {
>>     if (!condition)
>>     {
>>         writefln("Assertion failed @ %s:%d", file, line);
>>         writefln(args);
>>         exit(1);
>>     }
>> }
>
> Nice. I thought of that, but for some reason I thought that you couldn't  
> have default args before variadic args.
>

tbh, I was unsure myself. Sometimes you should just try. :p

-- 
Simen
September 02, 2012
Re: Trouble creating a formatted assert wrapper
>>> void myAssert(int line = __LINE__, string file = __FILE__, 
>>> Args...)(lazy bool condition, lazy Args args) {

Won't that create "template code bloat" ? Ie everytime myAssert 
is used a new function is created.

There was if I remember some discussion regarding not passing 
__LINE__,__FILE__ in assert related functions because of that.

If backtrace worked properly we should be able to go up the stack 
and get line number information when the assert fails (no time 
penalty when assert doesn't fail).

Another option is to use a lazy tuple argument inside myAssert 
instead of variadic arguments, which allows to pass line and file 
AFTER, without template bloat.

A related question:
In C++ we can stringify arguments and use it to provide 
informative asserts without duplicating code specifying a string 
version of the condition:
#define assert( isOK ) ( (isOK) ? (void)0 : 
(void)myAssert(#isOK,__LINE__,__PRETTY_FUNCTION__, __FILE__) )

Likewise for related quick debug functions:
#define DEBUG(val) myDEBUG(#val,val)

There seems to be no way of doing this currently (besides the 
ugly mixin(myAssertString("i==0")) which would parse the 
condition at CT).

Would that be possible to add?
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sun, Sep 2, 2012 at 8:46 PM, Peter Alexander
<peter.alexander.au@gmail.com> wrote:
> On Sunday, 2 September 2012 at 18:23:48 UTC, Simen Kjaeraas wrote:
>>
>> void myAssert(int line = __LINE__, string file = __FILE__, Args...)(lazy
>> bool condition, lazy Args args) {
>>     if (!condition)
>>     {
>>         writefln("Assertion failed @ %s:%d", file, line);
>>         writefln(args);
>>         exit(1);
>>     }
>> }
>
>
> Nice. I thought of that, but for some reason I thought that you couldn't
> have default args before variadic args.
>

IIRC, you can even have them before standard template args. Template
arguments are much more versatile (or hard-working) than function
arguments.
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sunday, 2 September 2012 at 19:31:24 UTC, timotheecour wrote:
>>>> void myAssert(int line = __LINE__, string file = __FILE__, 
>>>> Args...)(lazy bool condition, lazy Args args) {
>
> Won't that create "template code bloat" ? Ie everytime myAssert 
> is used a new function is created.

You can easily counter that by delegating the body to a 
non-template function.

Even then, it's only in non-release builds and it's a small 
function anyway.
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On 09/02/2012 07:14 PM, Peter Alexander wrote:
> One thing that's always bothered me is that I have to use
> std.string.format to produce useful assert messages:
>
> assert(x == 1, format("x doesn't equal 1, it is %d", x));
>
>
> Of course, I tried to solve this by producing my own assert-like
> function wrapper:
>
> void myAssert(Args...)(lazy bool condition, lazy Args args)
> {
>      assert(condition, format(args));
> }
>
>
> That's all good, but the problem now is that I get the wrong file and
> line in the assert message, so I tried to use the default arg __FILE__
> and __LINE__ trick:
>
> void myAssert(Args...)(lazy bool condition, lazy Args args, int line =
> __LINE__, string file = __FILE__)
> {
>      if (!condition)
>      {
>          writeln("Assertion failed @ %s:%d", file, line);
>          writefln(args);
>          exit(1);
>      }
> }
>
>
> But I can't have default arguments because of the variadic arguments!
>
> Can anyone think of a way around this?

I don't think there is a deep reason why IFTI shouldn't succeed in this 
case.
September 02, 2012
Re: Trouble creating a formatted assert wrapper
On Sunday, 2 September 2012 at 20:30:26 UTC, Timon Gehr wrote:
> On 09/02/2012 07:14 PM, Peter Alexander wrote:
>> One thing that's always bothered me is that I have to use
>> std.string.format to produce useful assert messages:
>>
>> assert(x == 1, format("x doesn't equal 1, it is %d", x));
>>
>>
>> Of course, I tried to solve this by producing my own 
>> assert-like
>> function wrapper:
>>
>> void myAssert(Args...)(lazy bool condition, lazy Args args)
>> {
>>     assert(condition, format(args));
>> }
>>
>>
>> That's all good, but the problem now is that I get the wrong 
>> file and
>> line in the assert message, so I tried to use the default arg 
>> __FILE__
>> and __LINE__ trick:
>>
>> void myAssert(Args...)(lazy bool condition, lazy Args args, 
>> int line =
>> __LINE__, string file = __FILE__)
>> {
>>     if (!condition)
>>     {
>>         writeln("Assertion failed @ %s:%d", file, line);
>>         writefln(args);
>>         exit(1);
>>     }
>> }
>>
>>
>> But I can't have default arguments because of the variadic 
>> arguments!
>>
>> Can anyone think of a way around this?
>
> I don't think there is a deep reason why IFTI shouldn't succeed 
> in this case.

Consider:

myAssert(false, "%d", 1);

What is Args? "%d", 1 could refer to the optional arguments, or 
the variadic arguments. Both match.
September 03, 2012
Re: Trouble creating a formatted assert wrapper
On Sunday, 2 September 2012 at 23:40:01 UTC, Peter Alexander 
wrote:
>
> Consider:
>
> myAssert(false, "%d", 1);
>
> What is Args? "%d", 1 could refer to the optional arguments, or 
> the variadic arguments. Both match.

Easy: the variadic arguments are not, themselves, optional.  
Match the variadic.  This kind of problem is already solved in 
every language with "scattering" assignments, and other such 
features.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home