Accessing __FILE__ and __LINE__ of caller in combination with varargs?

Anonymouse via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Apr 17 06:20:17 PDT 2016


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"));
}


More information about the Digitalmars-d-learn mailing list