Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-17 Thread Anonymouse via Digitalmars-d-learn

On Saturday, 16 April 2016 at 12:37:46 UTC, Simen Kjaeraas wrote:
On Saturday, 16 April 2016 at 00:03:59 UTC, Jonathan M Davis 
wrote:
On Friday, April 15, 2016 20:52:42 WebFreak001 via 
Digitalmars-d-learn wrote:



void assertf(string file = __FILE__, size_t line = __LINE__,
Args...)(lazy bool condition, in string message, Args args) {


Yes, you can do that, but do _not_ do that unless you really 
have no other choice. What you need to realize is that because 
the file and line number arguments will be unique for every 
call to this function, it will generate a new instantiation of 
it _every_ time it is called. So, you're going to get a lot of 
code bloat. There are rare cases where such bloat would be 
acceptable, but in the general case, it's a terrible thing to 
do. This particular case might be acceptable given how short 
it is, but in general, using __FILE__ or __LINE__ as template 
arguments should be avoided like the plague.


A few tricks to reduce this bloat:

[...]


You can also use tuple() to get Args to be a single type, and 
.expand it for the format call. But it will naturally still be 
one template instantiation per combination of tuple argument 
types.



import std.typecons : tuple;

void assertf(Args)(lazy bool condition, string pattern, Args args,
   string file = __FILE__, size_t line = __LINE__)
{
import std.format : format;
assert(condition, format("%s:%d | ", file, line) ~ 
format(pattern, args.expand));

}


void assertf(lazy bool condition, string message, /* no Args */
 string file = __FILE__, size_t line = __LINE__)
{
// add a tuple and bounce to the other assertf
assertf(condition, message, tuple(), file, line);
}


void main()
{
assertf(true, "normal message without tuple following it gets 
an empty tuple tacked on");
assertf(false, "%d comes after %d, says %s", tuple(1, 2, 
"wikipedia"));

}


Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-16 Thread Simen Kjaeraas via Digitalmars-d-learn
On Saturday, 16 April 2016 at 00:03:59 UTC, Jonathan M Davis 
wrote:
On Friday, April 15, 2016 20:52:42 WebFreak001 via 
Digitalmars-d-learn wrote:



void assertf(string file = __FILE__, size_t line = __LINE__,
Args...)(lazy bool condition, in string message, Args args) {


Yes, you can do that, but do _not_ do that unless you really 
have no other choice. What you need to realize is that because 
the file and line number arguments will be unique for every 
call to this function, it will generate a new instantiation of 
it _every_ time it is called. So, you're going to get a lot of 
code bloat. There are rare cases where such bloat would be 
acceptable, but in the general case, it's a terrible thing to 
do. This particular case might be acceptable given how short it 
is, but in general, using __FILE__ or __LINE__ as template 
arguments should be avoided like the plague.


A few tricks to reduce this bloat:

- Write a small wrapper. This will still give bloat, but only of
small functions:

void assertf(string file = __FILE__, size_t line = __LINE__, 
Args...)(lazy bool condition, in string message, Args args) {

assertfImpl(file, line, condition, message, args);
}

- Only care about line numbers in debug mode. Makes debug more 
bloated, code less readable, and you lose out on line numbers in 
release. Still worth it occasionally:


version (debug) {
void foo(string file = __FILE__, size_t line = __LINE__, 
Args...)(Args args) {

// Stuffs.
}
} else {
void assertf(Args...)(Args args) {
// Stuffs.
}
}

I'd love to have a way to pass the file and line number info as 
regular parameters, though. Something like:


void foo(Args...)(Args args, string file = __FILE__, int line = 
__LINE__) {}


Sadly, currently not possible. Maybe we could overload @disable 
for this purpose?


void foo(Args...)(Args args, @disable string file = __FILE__, 
@disable int line = __LINE__) {}


--
  Simen


Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-16 Thread WebFreak001 via Digitalmars-d-learn
On Saturday, 16 April 2016 at 00:03:59 UTC, Jonathan M Davis 
wrote:
Yes, you can do that, but do _not_ do that unless you really 
have no other choice. What you need to realize is that because 
the file and line number arguments will be unique for every 
call to this function, it will generate a new instantiation of 
it _every_ time it is called. So, you're going to get a lot of 
code bloat. There are rare cases where such bloat would be 
acceptable, but in the general case, it's a terrible thing to 
do. This particular case might be acceptable given how short it 
is, but in general, using __FILE__ or __LINE__ as template 
arguments should be avoided like the plague.


yeah I know that but there is really no other way in this case 
because of the varargs. Also because of the varargs the function 
will be different most of the time when always passing different 
arguments. There should be some "give me location of caller" 
keyword in D


Also, to nitpick your exact implementation, debug blocks and 
assertions aren't even vaguely related. debug blocks are used 
with the -debug flag with the intention of being used for 
printing out additional debug information (and getting around 
restrictions with pure with those messages while you're at it). 
They have nothing to do with -release, which is what controls 
assertions. What you really want to be doing is to use 
version(assert), not debug.


right, makes sense because there is a release with assertion 
flags.





Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-15 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, April 15, 2016 20:52:42 WebFreak001 via Digitalmars-d-learn wrote:
> On Friday, 15 April 2016 at 20:43:08 UTC, pineapple wrote:
> > I've written a very handy assertf method whose signature looks
> > like this:
> >
> > void assertf(Args...)(lazy bool condition, in string message,
> > Args args)
> >
> > But I'd also like to access the caller's file and line to use
> > them in constructing a thrown AssertError, and I'm stumbling on
> > how I can get that information where it needs to go. Help?
>
> void assertf(string file = __FILE__, size_t line = __LINE__,
> Args...)(lazy bool condition, in string message, Args args) {

Yes, you can do that, but do _not_ do that unless you really have no other
choice. What you need to realize is that because the file and line number
arguments will be unique for every call to this function, it will generate a
new instantiation of it _every_ time it is called. So, you're going to get a
lot of code bloat. There are rare cases where such bloat would be
acceptable, but in the general case, it's a terrible thing to do. This
particular case might be acceptable given how short it is, but in general,
using __FILE__ or __LINE__ as template arguments should be avoided like the
plague.

>  debug {
>  if (!condition) {
>  writeln(format(message, args) ~ format(" in %s:%s",
> file, line));
>  throw new AssertError();
>  }
>  }
> }

Also, to nitpick your exact implementation, debug blocks and assertions
aren't even vaguely related. debug blocks are used with the -debug flag with
the intention of being used for printing out additional debug information
(and getting around restrictions with pure with those messages while you're
at it). They have nothing to do with -release, which is what controls
assertions. What you really want to be doing is to use version(assert), not
debug.

- Jonathan M Davis



Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-15 Thread pineapple via Digitalmars-d-learn

On Friday, 15 April 2016 at 20:52:42 UTC, WebFreak001 wrote:
void assertf(string file = __FILE__, size_t line = __LINE__, 
Args...)(lazy bool condition, in string message, Args args) {


Aha, you are the best. Thanks!


Re: Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-15 Thread WebFreak001 via Digitalmars-d-learn

On Friday, 15 April 2016 at 20:43:08 UTC, pineapple wrote:
I've written a very handy assertf method whose signature looks 
like this:


void assertf(Args...)(lazy bool condition, in string message, 
Args args)


But I'd also like to access the caller's file and line to use 
them in constructing a thrown AssertError, and I'm stumbling on 
how I can get that information where it needs to go. Help?


void assertf(string file = __FILE__, size_t line = __LINE__, 
Args...)(lazy bool condition, in string message, Args args) {

debug {
if (!condition) {
writeln(format(message, args) ~ format(" in %s:%s", 
file, line));

throw new AssertError();
}
}
}

---

didn't test it but it should work (replace the content of the 
function with what you actually need, this is just some 
placeholder)


Accessing __FILE__ and __LINE__ of caller in combination with varargs?

2016-04-15 Thread pineapple via Digitalmars-d-learn
I've written a very handy assertf method whose signature looks 
like this:


void assertf(Args...)(lazy bool condition, in string message, 
Args args)


But I'd also like to access the caller's file and line to use 
them in constructing a thrown AssertError, and I'm stumbling on 
how I can get that information where it needs to go. Help?