www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Method overloading without Type2Type

reply Benjamin Thaut <code benjamin-thaut.de> writes:
I'm just reading Andreis book "Modern C++ Design" and try to translate a 
few examples to D 2. My most recent test looks as follows:

import std.stdio;

struct Type2Type(T){
	typedef T OriginalType;
}

class foo(T,R...) : foo!(R) {
	public void print(){
		super.print();
		writefln(T.stringof);
	}
	
	alias foo!(R).echo echo;
	public void echo(Type2Type!(T)) {
		writefln(T.stringof);
	}
}

class foo(T){
	public void print(){
		writefln("end " ~ T.stringof);
	}
	
	public void echo(Type2Type!(T)) {
		writefln(T.stringof);
	}
}

void main(string[] args){
	auto test = new foo!(int,float,double,short,byte)();
	test.print();
	
	test.echo(Type2Type!(double)());
	test.echo(Type2Type!(short)());
}

I'm wondering if there is any way in D 2 to not use Type2Type so that 
the calls to echo would look like:
test.echo!(double)();
test.echo!(short)();

The solution does not have to use inheritance, any idea?
-- 
Kind Regards
Benjamin Thaut
Apr 25 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Benjamin Thaut:

 import std.stdio;
 
 struct Type2Type(T){
 	typedef T OriginalType;
 }
 
 class foo(T,R...) : foo!(R) {
 	public void print(){
 		super.print();
 		writefln(T.stringof);
 	}
 	
 	alias foo!(R).echo echo;
 	public void echo(Type2Type!(T)) {
 		writefln(T.stringof);
 	}
 }
 
 class foo(T){
 	public void print(){
 		writefln("end " ~ T.stringof);
 	}
 	
 	public void echo(Type2Type!(T)) {
 		writefln(T.stringof);
 	}
 }
 
 void main(string[] args){
 	auto test = new foo!(int,float,double,short,byte)();
 	test.print();
 	
 	test.echo(Type2Type!(double)());
 	test.echo(Type2Type!(short)());
 }
Try to compile that code with "-w" (warnings). Bye, bearophile
Apr 26 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
 Try to compile that code with "-w" (warnings).
http://d.puremagic.com/issues/show_bug.cgi?id=3836 Bye, bearophile
Apr 26 2011
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.04.2011 13:43, schrieb bearophile:
 Try to compile that code with "-w" (warnings).
http://d.puremagic.com/issues/show_bug.cgi?id=3836 Bye, bearophile
Thanks, but that is not connected to my question at all, I want to implement the echo method so that the type is passed as a template argument, and not as a function argument. While that is happening I still want to be able to overload the function. Is this possible in D 2? -- Kind Regards Benjamin Thaut
Apr 26 2011
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Apr 26, 2011 at 18:41, Benjamin Thaut <code benjamin-thaut.de> wrote:
 Thanks, but that is not connected to my question at all,
 I want to implement the echo method so that the type is passed as a template
 argument, and not as a function argument. While that is happening I still
 want to be able to overload the function.
 Is this possible in D 2?
I'm not sure I understand what you're trying to do (didn't read "Modern C++ design"). Here is something that compiles: import std.stdio; class Foo(T,R...) : Foo!(R) { public void print(){ writeln(T.stringof); super.print(); } public void echo(U)(U u = U.init) { writeln(U.stringof); } } class Foo(T){ public void print(){ writeln("end: " ~ T.stringof); } public void echo(U)(U u = U.init) { writeln(U.stringof); } } void main(string[] args){ auto test = new Foo!(int,float,double,short,byte)(); test.print(); test.echo!double; test.echo!short; } I don't know if classes are necessary for what you've in mind. I tend to use structs: import std.stdio; struct Foo(T,R...) { void print(){ static if (R.length) { Foo!(R) fr; fr.print; } writeln(T.stringof); } void echo(U)(U u = U.init) { writefln(U.stringof);} } void main(string[] args){ Foo!(int,float,double,short,byte) test; test.print; test.echo!double; test.echo!short; }
Apr 26 2011
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.04.2011 21:55, schrieb Philippe Sigaud:
 On Tue, Apr 26, 2011 at 18:41, Benjamin Thaut<code benjamin-thaut.de>  wrote:
 Thanks, but that is not connected to my question at all,
 I want to implement the echo method so that the type is passed as a template
 argument, and not as a function argument. While that is happening I still
 want to be able to overload the function.
 Is this possible in D 2?
I'm not sure I understand what you're trying to do (didn't read "Modern C++ design"). Here is something that compiles: import std.stdio; class Foo(T,R...) : Foo!(R) { public void print(){ writeln(T.stringof); super.print(); } public void echo(U)(U u = U.init) { writeln(U.stringof); } } class Foo(T){ public void print(){ writeln("end: " ~ T.stringof); } public void echo(U)(U u = U.init) { writeln(U.stringof); } } void main(string[] args){ auto test = new Foo!(int,float,double,short,byte)(); test.print(); test.echo!double; test.echo!short; }
The Problem with that version is, that the code that is generated looks like void main(string[] args){ auto test = new Foo!(int,float,double,short,byte)(); test.print(); test.echo!double(double.init); test.echo!short(short.init); } If the types that are used, are no simple data types, but rather large structs, they are copied on every function call. Thats exactly what I want to avoid. The Type2Type template has a size of 0, thats why I'm using that in the first place. -- Kind Regards Benjamin Thaut
Apr 26 2011
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Apr 26, 2011 at 22:06, Benjamin Thaut <code benjamin-thaut.de> wrot=
e:
 The Problem with that version is, that the code that is generated looks l=
ike
 void main(string[] args){
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto test =3D new Foo!(int,float,double,short=
,byte)();
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 test.print();
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 test.echo!double(double.init);
 =C2=A0 =C2=A0 =C2=A0 =C2=A0test.echo!short(short.init);
 }

 If the types that are used, are no simple data types, but rather large
 structs, they are copied on every function call. Thats exactly what I wan=
t
 to avoid. The Type2Type template has a size of 0, thats why I'm using tha=
t
 in the first place.
In that case, just use echo(U)() { ...}, like this: import std.stdio; class Foo(T,R...) : Foo!(R) { public void print(){ writefln(T.stringof); super.print(); } public void echo(U)() { writefln(U.stringof); } } class Foo(T){ public void print(){ writefln("end: " ~ T.stringof); } public void echo(U)() { writefln(U.stringof); } } void main(string[] args){ auto test =3D new Foo!(int,float,double,short,byte)(); test.print(); test.echo!double; test.echo!short; } What's your global goal with this construction? What are you trying to achi= eve?
Apr 26 2011
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 26.04.2011 22:41, schrieb Philippe Sigaud:
 On Tue, Apr 26, 2011 at 22:06, Benjamin Thaut<code benjamin-thaut.de>  wrote:
 The Problem with that version is, that the code that is generated looks like

 void main(string[] args){
          auto test = new Foo!(int,float,double,short,byte)();
          test.print();
          test.echo!double(double.init);
         test.echo!short(short.init);
 }

 If the types that are used, are no simple data types, but rather large
 structs, they are copied on every function call. Thats exactly what I want
 to avoid. The Type2Type template has a size of 0, thats why I'm using that
 in the first place.
In that case, just use echo(U)() { ...}, like this: import std.stdio; class Foo(T,R...) : Foo!(R) { public void print(){ writefln(T.stringof); super.print(); } public void echo(U)() { writefln(U.stringof); } } class Foo(T){ public void print(){ writefln("end: " ~ T.stringof); } public void echo(U)() { writefln(U.stringof); } } void main(string[] args){ auto test = new Foo!(int,float,double,short,byte)(); test.print(); test.echo!double; test.echo!short; } What's your global goal with this construction? What are you trying to achieve?
struct Foo {...} struct Bar {...} void* poolAllocate(size_t sz){...}; abstract class Allocator(T){ //needs to be implemented by user to fill obj with data public abstract void init(ref T obj); public void make(Type2Type!(T)){ void* ptr = poolAllocate(T.sizeof); T* obj = emplace!(T)(ptr[0..T.sizeof]); init(*obj); } abstract void produce(); } abstract class Allocator(T,R...) : Allocator!(R) { //needs to be implemented by user to fill obj with data public abstract void init(ref T obj); alias Allocator!(R).make make; public void make(Type2Type!(T)){ void* ptr = poolAllocate(T.sizeof); T* obj = emplace!(T)(ptr[0..T.sizeof]); init(*obj); } } class UserImpl : Allocator!(Foo,Bar){ override void init(ref Foo obj){ //fill Foo with data } override void init(ref Bar obj){ //fill Bar with data } override void produce(){ for(...){ make(Type2Type!(Foo)); } for(...){ make(Type2Type!(Bar)); } } } I do this to hide away allocation and pointer arithmetic from the user. -- Kind Regards Benjamin Thaut
Apr 26 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Benjamin Thaut:

 The Type2Type template has a size of 0, thats why I'm 
 using that in the first place.
Almost. Maybe to allow addressability with pointers the minimal struct size in D is 1 byte (0-length fixed-sized arrays may require zero bytes on DMD and 1 bit on LDC): struct Type2Type(T){ typedef T OriginalType; } static assert ((Type2Type!int).sizeof == 1); void main() {} Bye, bearophile
Apr 26 2011