www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Access derived type in baseclass static function template

reply Timoses <timosesu gmail.com> writes:
Hey,

wondering whether it's possible to access the derived type from a 
function template in the base class or interface.

this T does not seem to be working, I guess because it's a static 
function and this does not exists?!


interface I
{
     static void test(this T)()
     {
         writeln(T.type.stringof);
     }
}

abstract class A
{
     static void test(this T)()
     {
         writeln(T.type.stringof);
     }
}

class B : A
{
     alias type = uint;
}
class C : I {
     alias type = int;
}

void main() {
	B.test();
	C.test();
}

Throws:
Error: template app.A.test cannot deduce function from argument 
types !()(), candidates are:
         app.A.test(this T)()
Error: template app.I.test cannot deduce function from argument 
types !()(), candidates are:
         app.I.test(this T)()


Any way I could accomplish this?
Aug 02
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/2/17 8:07 AM, Timoses wrote:
 Hey,
 
 wondering whether it's possible to access the derived type from a 
 function template in the base class or interface.
 
 this T does not seem to be working, I guess because it's a static 
 function and this does not exists?!
Yep.
 Any way I could accomplish this?
Move test outside the interface: void test(C)(C c) if(is(C : I)) { writeln(C.type.stringof); } Though, at that point, you don't need I. I'm assuming you have a more complex real-world example. -Steve
Aug 02
parent reply Timoses <timosesu gmail.com> writes:
On Wednesday, 2 August 2017 at 12:49:12 UTC, Steven Schveighoffer 
wrote:
 On 8/2/17 8:07 AM, Timoses wrote:
 Hey,
 
 wondering whether it's possible to access the derived type 
 from a function template in the base class or interface.
 
 this T does not seem to be working, I guess because it's a 
 static function and this does not exists?!
Yep.
 Any way I could accomplish this?
Move test outside the interface: void test(C)(C c) if(is(C : I)) { writeln(C.type.stringof); } Though, at that point, you don't need I. I'm assuming you have a more complex real-world example. -Steve
Thanks for the reply! Not sure I understand correctly, though. interface I {} class A : I {} void test(T)(T t) if(is(T: I)) { writeln(T.type.stringof); } void main() { A.test; } throws: Error: no property 'test' for type 'app.A' which it of course does... test(A) makes no sense either. I need to call it statically and want to know the derived class type in the base class (or interface) function template. Is there a trick in your answer? : P
Aug 02
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/2/17 9:11 AM, Timoses wrote:
 On Wednesday, 2 August 2017 at 12:49:12 UTC, Steven Schveighoffer wrote: 
 Thanks for the reply!
 
 Not sure I understand correctly, though.
 
 interface I {}
 class A : I {}
 
 void test(T)(T t) if(is(T: I))
 { writeln(T.type.stringof); }
 
 void main()
 {
      A.test;
 }
 
 throws:
    Error: no property 'test' for type 'app.A'
 
 which it of course does... test(A) makes no sense either.
 I need to call it statically and want to know the derived class type in 
 the base class (or interface) function template.
 
 Is there a trick in your answer? : P
Sorry, I didn't read your original post thoroughly, you need an instance to make this work properly. A a; a.test; // should work What you are looking for is virtual static methods, and D doesn't have those. I don't know if there's a way to make it work with existing features. However, your original code has potential as an enhancement request, as the type is known at compile-time and could certainly be resolved to pass in as the `this` template parameter. -Steve
Aug 02
parent reply Arafel <er.krali gmail.com> writes:
 
 What you are looking for is virtual static methods, and D doesn't have 
 those. I don't know if there's a way to make it work with existing 
 features.
 
Well, there are interesting things to do: https://dpaste.dzfl.pl/ed826ae21473 I don't know if that's what one would call "virtual static", but I'd say it comes close...
Aug 02
parent reply Timoses <timosesu gmail.com> writes:
Thanks Arafel, the alias workaround might just be a nice way to 
put it.

On Wednesday, 2 August 2017 at 13:51:01 UTC, Steven Schveighoffer 
wrote:
 What you are looking for is virtual static methods, and D 
 doesn't have those. I don't know if there's a way to make it 
 work with existing features.
I'm not looking to overwrite the static method (which would refer to virtual, right?). The solution I had previously was: interface I { static void test(T)() { writeln(T.stringof); } } class B : I { alias type = int; static void test() { I.test!type(); } } void main() { B.test(); } However, this requires to add the base type as in I.test!type(); otherwise (only test!type();) it complains about Error: template instance test!type test is not a template declaration, it is a function I was hoping there was a way to simply define it in the base class/interface without producing redundant code in each derived class. Arafel's solution gets very close! On Wednesday, 2 August 2017 at 13:51:01 UTC, Steven Schveighoffer wrote:
 However, your original code has potential as an enhancement 
 request, as the type is known at compile-time and could 
 certainly be resolved to pass in as the `this` template 
 parameter.
I guess the `this` is really misleading it being a static method. I suppose https://issues.dlang.org/buglist.cgi?bug_severity=enhancement&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=D&query_format=report-table&y_axi _field=bug_severity would be the place for an enhancement request? Possibly related: https://issues.dlang.org/show_bug.cgi?id=14191 On Wednesday, 2 August 2017 at 14:23:26 UTC, Arafel wrote:
 
 What you are looking for is virtual static methods, and D 
 doesn't have those. I don't know if there's a way to make it 
 work with existing features.
 
Well, there are interesting things to do: https://dpaste.dzfl.pl/ed826ae21473 I don't know if that's what one would call "virtual static", but I'd say it comes close...
Nifty, but still doesn't allow knowing the derived type B in the foo method of A, does it?
Aug 02
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 8/2/17 11:06 AM, Timoses wrote:
 On Wednesday, 2 August 2017 at 13:51:01 UTC, Steven Schveighoffer wrote:
 However, your original code has potential as an enhancement request, 
 as the type is known at compile-time and could certainly be resolved 
 to pass in as the `this` template parameter.
I guess the `this` is really misleading it being a static method. I suppose https://issues.dlang.org/buglist.cgi?bug_severity=enhancement&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=D&query_format=report-table&y_axi _field=bug_severity would be the place for an enhancement request? Possibly related: https://issues.dlang.org/show_bug.cgi?id=14191
Yes, that's exactly it. Note that typeof(this) has special meaning for static methods: class C { static typeof(this) foo() { return new typeof(this); } } So there is precedence for the meaning of `this` in a static context. -Steve
Aug 02
parent Timoses <timosesu gmail.com> writes:
On Wednesday, 2 August 2017 at 15:38:12 UTC, Steven Schveighoffer 
wrote:
 On 8/2/17 11:06 AM, Timoses wrote:
 On Wednesday, 2 August 2017 at 13:51:01 UTC, Steven 
 Schveighoffer wrote:
 However, your original code has potential as an enhancement 
 request, as the type is known at compile-time and could 
 certainly be resolved to pass in as the `this` template 
 parameter.
I guess the `this` is really misleading it being a static method. I suppose https://issues.dlang.org/buglist.cgi?bug_severity=enhancement&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=D&query_format=report-table&y_axi _field=bug_severity would be the place for an enhancement request? Possibly related: https://issues.dlang.org/show_bug.cgi?id=14191
Yes, that's exactly it. Note that typeof(this) has special meaning for static methods: class C { static typeof(this) foo() { return new typeof(this); } } So there is precedence for the meaning of `this` in a static context. -Steve
Oh, just now get it after creating the issue ^^. Makes sense. I kind of connected the "this" to existing instances because the DMD compiler often complains about something like "need this for..." when calling something from a static method that... well... needs "this" or instantiation.. E.g.: class A { static void a() { b(); } void b(); } will throw Error: need 'this' for 'b' of type 'void()'
Aug 03
prev sibling next sibling parent Arafel <er.krali gmail.com> writes:
On 08/02/2017 02:07 PM, Timoses wrote:
 Hey,
 
 wondering whether it's possible to access the derived type from a 
 function template in the base class or interface.
 
 this T does not seem to be working, I guess because it's a static 
 function and this does not exists?!
 
 
[...]
 
 Any way I could accomplish this?
Well, it's a clumsy workaround, but the only thing missing seems to be the "this T" automatic deduction. I was recently hit by something similar: the "this" parameter deduction only works for instance methods. It was not totally clear if it was a bug or a feature... The documentation [1] is however quite clear:
 TemplateThisParameters are used in member function templates to pick up the
type of the this reference. 
So, static functions doesn't seem to be covered. You can, however, make it explicit: ``` B.test!B(); C.test!C(); ``` And then even alias it to prevent accidental mismatches: ``` import std.stdio; interface I { static void test(this T)() { writeln(T.type.stringof); } } abstract class A { static void test(this T)() { writeln(T.type.stringof); } } class B : A { alias type = uint; } class C : I { alias type = int; } void main() { test!B(); test!C(); } alias test(T) = T.test!T; ``` [1]: http://dlang.org/spec/template.html#TemplateThisParameter
Aug 02
prev sibling parent Timoses <timosesu gmail.com> writes:
On Wednesday, 2 August 2017 at 12:07:46 UTC, Timoses wrote:
 Hey,

 wondering whether it's possible to access the derived type from 
 a function template in the base class or interface.

 [...]
Created an enhancement issue: https://issues.dlang.org/show_bug.cgi?id=17714
Aug 03