Thread overview
Weird link error
Apr 20, 2015
CodeSun
Apr 20, 2015
Adam D. Ruppe
Apr 20, 2015
anonymous
Apr 20, 2015
Baz
April 20, 2015
I have test a snippet of code, and I encountered with a weird link error.
The following is the demo:

import std.stdio;
interface Ti {
	T get(T)(int num);
	T get(T)(string str);
}

class Test : Ti {
	T get(T)(int num) {
		writeln("ok");
	}
	T get(T)(string str) {
		writeln(str);
	}
}
void main() {
	Ti tt = new Test;
	tt.get!string("test");
	tt.get!string(123);
}


When I use dmd to compile this code snippet, the following link error was reported:
tt.d:(.text._Dmain+0x3b):‘_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya’ undefined reference
tt.d:(.text._Dmain+0x49):‘_D2tt2Ti12__T3getTAyaZ3getMFiZAya’undefined reference

And if I modigy the code to
Test tt = new Test;

then this code will work.

So does it mean I can't declare function template inside interface? If so, why didn't dmd report the error while compiling instead of linking?

And where I can find the D symbol definition, because information like ‘_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya’ makes me really confused.
April 20, 2015
On Monday, 20 April 2015 at 17:02:18 UTC, CodeSun wrote:
> So does it mean I can't declare function template inside interface?

You can, but they are considered final so a body is required to use them - they aren't just a pointer to the derived implementation.
April 20, 2015
On Monday, 20 April 2015 at 17:02:18 UTC, CodeSun wrote:
> I have test a snippet of code, and I encountered with a weird link error.
> The following is the demo:
>
> import std.stdio;
> interface Ti {
> 	T get(T)(int num);
> 	T get(T)(string str);
> }
>
> class Test : Ti {
> 	T get(T)(int num) {
> 		writeln("ok");
> 	}
> 	T get(T)(string str) {
> 		writeln(str);
> 	}
> }
> void main() {
> 	Ti tt = new Test;
> 	tt.get!string("test");
> 	tt.get!string(123);
> }
>
>
> When I use dmd to compile this code snippet, the following link error was reported:
> tt.d:(.text._Dmain+0x3b):‘_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya’ undefined reference
> tt.d:(.text._Dmain+0x49):‘_D2tt2Ti12__T3getTAyaZ3getMFiZAya’undefined reference
>
> And if I modigy the code to
> Test tt = new Test;
>
> then this code will work.

Template methods are non-virtual. That is, you can't override them.

> So does it mean I can't declare function template inside interface? If so, why didn't dmd report the error while compiling instead of linking?

You can theoretically implement them elsewhere. For example, this works:

----
module test;

interface Ti {
    T get(T)(int num);
    T get(T)(string str);
}

pragma(mangle, "_D4test2Ti12__T3getTAyaZ3getMFiZAya") string impl(int)
{
    return "foo";
}
pragma(mangle, "_D4test2Ti12__T3getTAyaZ3getMFAyaZAya") string impl(string)
{
    return "bar";
}

class Test : Ti {}

void main() {
    Ti tt = new Test;
    tt.get!string("test");
    tt.get!string(123);
}
----

It's really silly, though. I don't know if there's a more realistic use case.

> And where I can find the D symbol definition, because information like ‘_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya’ makes me really confused.

That's a mangled name. There's a tool called ddemangle. It comes with the D releases. You can pipe the compiler output through it to get more readable symbol names (don't forget to redirect stderr to stdout). For this one it gives gives you "immutable(char)[] tt.Ti.get!(immutable(char)[]).get(immutable(char)[])".
April 20, 2015
On Monday, 20 April 2015 at 17:02:18 UTC, CodeSun wrote:
>
> And where I can find the D symbol definition, because information like ‘_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya’ makes me really confused.

---
import std.demangle;
auto friendlySymbol = demangle("_D2tt2Ti12__T3getTAyaZ3getMFAyaZAya");
---