www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template method in interfaces

reply Arafel <er.krali gmail.com> writes:
I'm not sure if the following is even expected to work, since I'm 
not sure how the vtable for the interface would look like (well, 
that would be applicable to any overriden templated method, 
though):

---
public interface I {
	void func(T)(T t);
}

public class C : I {
	void func(T)(T t) {
	}
}

void main() {
	I i = new C();
	i.func(1);
}
---

But since the error I get is in the linker, and not in the 
compiler, I guess that's somehow a bug? Or how should it work 
then?

https://dpaste.dzfl.pl/7a14fa074673

/d31/f76.o: In function `_Dmain': /d31/f76.d:(.text._Dmain+0x24): 
undefined reference to `_D3f761I11__T4funcTiZ4funcMFiZv' 
collect2: error: ld returned 1 exit status --- errorlevel 1

PS: Now I see [1] that it shouldn't, so perhaps the compiler 
should reject templated methods in interfaces from the beginning?

[1]: http://forum.dlang.org/post/jg504s$1f7t$1 digitalmars.com
Aug 10 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 10 August 2016 at 15:20:37 UTC, Arafel wrote:
 I'm not sure if the following is even expected to work, since 
 I'm not sure how the vtable for the interface would look like 
 (well, that would be applicable to any overriden templated 
 method, though):

 ---
 public interface I {
 	void func(T)(T t);
 }

 public class C : I {
 	void func(T)(T t) {
 	}
 }

 void main() {
 	I i = new C();
 	i.func(1);
 }
 ---

 But since the error I get is in the linker, and not in the 
 compiler, I guess that's somehow a bug? Or how should it work 
 then?

 https://dpaste.dzfl.pl/7a14fa074673

 /d31/f76.o: In function `_Dmain': 
 /d31/f76.d:(.text._Dmain+0x24): undefined reference to 
 `_D3f761I11__T4funcTiZ4funcMFiZv' collect2: error: ld returned 
 1 exit status --- errorlevel 1

 PS: Now I see [1] that it shouldn't, so perhaps the compiler 
 should reject templated methods in interfaces from the 
 beginning?

 [1]: http://forum.dlang.org/post/jg504s$1f7t$1 digitalmars.com
Because templated functions cannot be virtual, it follows that I.func is final. Having no body, the compiler thinks that its body will be found by the linker in another object file, but this does not happen, so the linker complains. Being I.func final, C.func just hides it, so you would not incur any problem if you called func explicitly on an object of type C. So what you found is not a bug, but some unintuitive behaviour due to templated functions being implicitly final and forward declarations. Maybe the compiler should emit a warning about implicitly-final functions in interfaces.
Aug 10 2016
parent reply Arafel <er.krali gmail.com> writes:
On Wednesday, 10 August 2016 at 15:25:40 UTC, Lodovico Giaretta 
wrote:
 Because templated functions cannot be virtual, it follows that 
 I.func is final. Having no body, the compiler thinks that its 
 body will be found by the linker in another object file, but 
 this does not happen, so the linker complains.
 Being I.func final, C.func just hides it, so you would not 
 incur any problem if you called func explicitly on an object of 
 type C.

 So what you found is not a bug, but some unintuitive behaviour 
 due to templated functions being implicitly final and forward 
 declarations. Maybe the compiler should emit a warning about 
 implicitly-final functions in interfaces.
Would it even make sense to "force" (deprecation warning) a "final" keyword in any implicitly-final function (I wasn't even aware of those, I have to admit)? It would make things much clearer, like with "override"...
Aug 10 2016
parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 10 August 2016 at 15:39:19 UTC, Arafel wrote:
 On Wednesday, 10 August 2016 at 15:25:40 UTC, Lodovico Giaretta 
 wrote:
 Because templated functions cannot be virtual, it follows that 
 I.func is final. Having no body, the compiler thinks that its 
 body will be found by the linker in another object file, but 
 this does not happen, so the linker complains.
 Being I.func final, C.func just hides it, so you would not 
 incur any problem if you called func explicitly on an object 
 of type C.

 So what you found is not a bug, but some unintuitive behaviour 
 due to templated functions being implicitly final and forward 
 declarations. Maybe the compiler should emit a warning about 
 implicitly-final functions in interfaces.
Would it even make sense to "force" (deprecation warning) a "final" keyword in any implicitly-final function (I wasn't even aware of those, I have to admit)? It would make things much clearer, like with "override"...
I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged.
Aug 10 2016
next sibling parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta 
wrote:
 On Wednesday, 10 August 2016 at 15:39:19 UTC, Arafel wrote:
 Would it even make sense to "force" (deprecation warning) a 
 "final" keyword in any implicitly-final function (I wasn't 
 even aware of those, I have to admit)? It would make things 
 much clearer, like with "override"...
I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged.
Anyway what I said about implicit final is true for classes. In classes, I don't like the idea of having to put an explicit final, but this is debatable. For interfaces, I'm ok with forcing an explicit final attribute (but as I said the spec does not allow templated functions in interfaces, even if the compiler does).
Aug 10 2016
parent reply Arafel <er.krali gmail.com> writes:
On Wednesday, 10 August 2016 at 15:52:29 UTC, Lodovico Giaretta 
wrote:
 On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta 
 wrote:
 On Wednesday, 10 August 2016 at 15:39:19 UTC, Arafel wrote:
 Would it even make sense to "force" (deprecation warning) a 
 "final" keyword in any implicitly-final function (I wasn't 
 even aware of those, I have to admit)? It would make things 
 much clearer, like with "override"...
I read the spec again, and found out that it says interfaces cannot contain templated functions... So either my interpretation is the intended one and the spec is outdated, or the spec is right and the compiler is bugged.
Anyway what I said about implicit final is true for classes. In classes, I don't like the idea of having to put an explicit final, but this is debatable. For interfaces, I'm ok with forcing an explicit final attribute (but as I said the spec does not allow templated functions in interfaces, even if the compiler does).
I have to say that the fact that this compiles at all seems like a bug to me according to [1], even more so that the method in A is called: --- import std.stdio; public class A { public void func(T)(T t) { writeln("Within A"); } } public class B : A { override public void func(T)(T t) { writeln("Within B"); } } void main() { A a = new B(); a.func(1); } --- https://dpaste.dzfl.pl/f3d5beff2e51 If the function is "final", even if implicitly so, the "override" should fail according to the spec as I, and I guess 99% of the people[2], understand it. [1]: https://dlang.org/spec/function.html#virtual-functions [2]: OK, technically not, since it just says that "Functions marked as final may not be overridden in a derived class [...]" and this function is not *marked* as final, but implicitly final... still...
Aug 10 2016
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/10/16 12:41 PM, Arafel wrote:

 I have to say that the fact that this compiles at all seems like a bug
 to me according to [1], even more so that the method in A is called:
That is definitely a bug. D ignores many misplaced attributes, but not override. -Steve
Aug 10 2016
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta 
wrote:
 I read the spec again, and found out that it says interfaces 
 cannot contain templated functions... So either my 
 interpretation is the intended one and the spec is outdated, or 
 the spec is right and the compiler is bugged.
Spec must be out of date, I remember this being a conscious decision to add them.
Aug 10 2016
parent Lodovico Giaretta <lodovico giaretart.net> writes:
On Wednesday, 10 August 2016 at 15:54:42 UTC, Adam D. Ruppe wrote:
 On Wednesday, 10 August 2016 at 15:48:10 UTC, Lodovico Giaretta 
 wrote:
 I read the spec again, and found out that it says interfaces 
 cannot contain templated functions... So either my 
 interpretation is the intended one and the spec is outdated, 
 or the spec is right and the compiler is bugged.
Spec must be out of date, I remember this being a conscious decision to add them.
Last line of this page: https://dlang.org/spec/template.html#limitations I'll file a bug report for this and an enhancement request for implicit final in interfaces.
Aug 10 2016