Thread overview
Method overloading without Type2Type
Apr 26, 2011
Benjamin Thaut
Apr 26, 2011
bearophile
Apr 26, 2011
bearophile
Apr 26, 2011
Benjamin Thaut
Apr 26, 2011
Philippe Sigaud
Apr 26, 2011
Benjamin Thaut
Apr 26, 2011
Philippe Sigaud
Apr 27, 2011
Benjamin Thaut
Apr 26, 2011
bearophile
April 26, 2011
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
April 26, 2011
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
April 26, 2011
> Try to compile that code with "-w" (warnings).

http://d.puremagic.com/issues/show_bug.cgi?id=3836

Bye,
bearophile
April 26, 2011
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
April 26, 2011
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;
}
April 26, 2011
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
April 26, 2011
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?
April 26, 2011
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
April 27, 2011
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