April 18, 2017
On Tuesday, 18 April 2017 at 10:13:09 UTC, Jonathan M Davis wrote:
> On Monday, April 17, 2017 07:23:50 Jonathan M Davis via Digitalmars-d-learn wrote:
>> 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
>
> Actually, not only is there already a bug report for this
>
> https://issues.dlang.org/show_bug.cgi?id=8687
>
> which is marked as a bug and not an enhancement, and when Walter commented on it when an ICE related to it was fixed, he didn't change it from a bug to an enhancement. So, it looks like he agrees that it's a bug rather than considering it an enhancement. It has yet to be fixed regardless though.
>
> - Jonathan M Davis

import std.stdio: writeln;
import std.conv: to;

void main()
{
    add("Scene 1", "Scene 2", "Scene 3");
    add("Scene 3", "Scene 4", "Scene 5");
    add(5, 6, 7);
    add(7, "Scene 8", "Scene 9");
    writeln("total scenes added: ", sceneCount);
}

struct Scene
{
    string name;
    string file;
    size_t line;
}

Scene*[] listOfScenes;
int[string] indexOfScenes;
int sceneCount = 0;

void add_impl(T...)(string file, size_t line, T args)
{
    foreach(arg; args)
    {
        static if (is(typeof(arg) == string))
        {
            auto name = arg;
        }
        else
        {
            auto name = "Scene " ~ arg.to!string;
        }
        if (name in indexOfScenes)
        {
            EError(file, line, "scene already exists", name);
        }
        else
        {
            indexOfScenes[name] = sceneCount;
            listOfScenes ~= new Scene(name, file, line);
            sceneCount += 1;
            writeln("added " ~ name);
        }
    }
}

void add(string file = __FILE__, size_t line = __LINE__, T...)(T args)
{
    add_impl!T(file, line, args);
}

void EError(string file, size_t line, string message, string name)
{
    writeln(name, ": ", message,
            " in file ", file, " in line ", line);
    auto previous = listOfScenes[indexOfScenes[name]];
    writeln("previous definition of ", previous.name,
            " was in ", previous.file, " in line ", previous.line);
}

/* output:

added Scene 1
added Scene 2
added Scene 3
Scene 3: scene already exists in file vlf.d in line 7
previous definition of Scene 3 was in vlf.d in line 6
added Scene 4
added Scene 5
Scene 5: scene already exists in file vlf.d in line 8
previous definition of Scene 5 was in vlf.d in line 7
added Scene 6
added Scene 7
Scene 7: scene already exists in file vlf.d in line 9
previous definition of Scene 7 was in vlf.d in line 8
added Scene 8
added Scene 9
total scenes added: 9

*/


I tried to produce an example of calling a function with
variadic template arguments using special tokens __FILE__ and __LINE__.

This compiles and runs, producing the output shown, using the default gdc
provided by Ubuntu 17.04. This appears to be a workaround for Issue 8687.
The instantiations of the wrapper function `add` should only add minimally
to the compiled object code size, once per call of `add`.
I'm not sure about the quality of any of this code.

April 18, 2017
On Tuesday, 18 April 2017 at 13:28:06 UTC, Solomon E wrote:

> I tried to produce an example of calling a function with
> variadic template arguments using special tokens __FILE__ and __LINE__.
>
> This compiles and runs, producing the output shown, using the default gdc
> provided by Ubuntu 17.04. This appears to be a workaround for Issue 8687...

There's a much more concise workaround, both in code written and generated ;)

import std.stdio;

template func(string file = __FILE__, int line = __LINE__)
{
    auto func(T...)(auto ref T args)
    {
        writeln("called func with ", T.length, " args at ",
                file, ":", line);
    }
}

void main()
{
    func();
    func(1, 2, 3);
}

April 18, 2017
On Tuesday, 18 April 2017 at 13:48:57 UTC, Stanislav Blinov wrote:
> On Tuesday, 18 April 2017 at 13:28:06 UTC, Solomon E wrote:
>
>> I tried to produce an example of calling a function with
>> variadic template arguments using special tokens __FILE__ and __LINE__.
>>
>> This compiles and runs, producing the output shown, using the default gdc
>> provided by Ubuntu 17.04. This appears to be a workaround for Issue 8687...
>
> There's a much more concise workaround, both in code written and generated ;)
>
> import std.stdio;
>
> template func(string file = __FILE__, int line = __LINE__)
> {
>     auto func(T...)(auto ref T args)
>     {
>         writeln("called func with ", T.length, " args at ",
>                 file, ":", line);
>     }
> }
>
> void main()
> {
>     func();
>     func(1, 2, 3);
> }

Thank you for reminding me that templates can contain a definition of a function
of the same name, which still surprises me as convenient, not as a bad thing.

Unfortunately, when I tried it, I found that while that attempt at a workaround is
twice as concise in lines of code and symbols introduced, it is not acceptable.
It gets the lines reported wrong. It reports the line for where the template was
first instantiated for the same tuple of argument types, instead of exactly the line
of each call of `func`.
April 19, 2017
On Monday, 17 April 2017 at 14:23:50 UTC, Jonathan M Davis wrote:
> On Monday, April 17, 2017 13:45:18 Dmitry via Digitalmars-d-learn wrote:
>> [...]
>
> Every time there's a new template instantiation, it's essentially copy-pasting the entire template. So, if you have the templated function
>
> [...]

The other reason to avoid excessive template instantiation is that it inflates your compile time. A while back I changed my custom assertf() and logf() functions to be non-templated in exactly the way Jonathan M Davis described, and it shaved ~0.5s off my 3s build time. This particular project is currently only 8000 LOC, but on a larger project you can see the hit could be pretty significant.
April 19, 2017
On Tuesday, 18 April 2017 at 13:48:57 UTC, Stanislav Blinov wrote:
> There's a much more concise workaround, both in code written and generated ;)
>
> import std.stdio;
>
> template func(string file = __FILE__, int line = __LINE__)
> {
>     auto func(T...)(auto ref T args)
>     {
>         writeln("called func with ", T.length, " args at ",
>                 file, ":", line);
>     }
> }
>
> void main()
> {
>     func();
>     func(1, 2, 3);
> }

Very nice. Thank you!
1 2
Next ›   Last »