hidden passing of __FILE__ and __LINE__ into function

Jonathan M Davis via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Apr 17 07:23:50 PDT 2017


On Monday, April 17, 2017 13:45:18 Dmitry via Digitalmars-d-learn wrote:
> On Monday, 17 April 2017 at 10:55:30 UTC, Jonathan M Davis wrote:
> > They works, but it results in a new template being instantiated
> > for every call, so you really shouldn't use __FILE__ or
> > __LINE__ as template arguments if you can avoid it.
>
> Does it matter if I anyway use template (S...) ?
> And what problem with that new templates for every call?
> Increases .exe size? Needs more memory (runtime? compile-time?)?
> Something else?

Every time there's a new template instantiation, it's essentially
copy-pasting the entire template. So, if you have the templated function

auto foo(T)(T bar)
{
    return bar;
}

and then call

foo(5);
foo(true);
foo("hello");

then you get the equivalent of

int foo!int(int bar)
{
    return bar;
}

bool foo!bool(bool bar)
{
    return bar;
}

string foo!string(string bar)
{
    return bar;
}

in your program. If you have

string foo(string file = __FILE__, size_t line = line)(string bar)
{
    return bar;
}

and you call that function 17 times, then you get 17 separate functions. If
you call it 120 times you get 120 separate functions. So, if you call the
function very many times, the template bloat would be enormous. The
executable will be _much_ larger and will thus take up much more space on
disk and much more RAM when it's loaded into memory. In some cases, that
makes sense, but it usually doesn't.

> > Usually, the better way to handle it is to use runtime
> > arguments, e.g.
> > void error(string msg, string file = __FILE__, size_t line =
> > __LINE__)
>
> Is possible use this with (S...)? In some cases I use many
> arguments (5-10, mixed strings and numbers) and I tried to avoid
> the concatenation them into string.
>
> What will be better? Concatenation or templates? Or maybe an
> another way?

The short answer is that if you're using variadic templates, you can't use
default arguments. Something like

auto foo(Args...)(Args args, string file = __FILE__, size_t line = __LINE__)
{
    ...
}

auto result = foo("hello", 42);

does not work. So, if you want to have the file and line number passed
automatically with a variadic template, then you're forced to use template
parameters instead of function paramaters and incur whatever bloat that goes
with that.

Now, that being said, surprisingly, it does look like it works to do

auto foo(Args...)(Args args, string file = __FILE__, size_t line = __LINE__)
{
    ...
}

auto result = foo!(string, int)("hello", 42);

So, if you're okay with explicitly instantiating your variadic function
template instead of having the types inferred, then it can work, but
otherwise, no. Making it work would require a language enhancement, and even
then, if you ever wanted to explicitly provide the file and line number
arguments instead of using the default arguments, you'd almost certainly be
forced to explicitly instantiate the template, since the compiler would have
no other way of determining whether the file and line arguments on the end
were intended to be the file and line arguments or just more variadic
arguments.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list