www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Templated Functions

reply Tomás Rossi <Tomás_member pathlink.com> writes:
In C++ one could do this:

template <class T>
void genericFunction<T>(someParam1, someParam2, ..., someParamN)
{...generic algorithm...}

and then:

..
genericFunction< list<int> >(blah blah ...);
..

Is this possible in D?

Tom
Oct 31 2005
parent reply "John C" <johnch_atms hotmail.com> writes:
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom 
Oct 31 2005
parent reply Tomás Rossi <Tomás_member pathlink.com> writes:
In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly! What about having some kind of anonymous template. (Please correct me if i'm wrong) Tom
Oct 31 2005
next sibling parent reply "John C" <johnch_atms hotmail.com> writes:
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk5lqe$1gar$1 digitaldaemon.com...
 In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template:
If you have a single member in the template, you don't have to.
 ///////////////////////////////////////
 template genericFunctions(T)
 {
 T genericFunction1() {return T.max;}
 T genericFunction2() {return T.min;}
 ..
 }

 toString( genericFunctions.genericFunction1!(int)() );
 toString( genericFunctions.genericFunction2!(int)() );
And that could be rewritten as: template genericFunction1(T) { T genericFunction1() { return T.max; } } template genericFunction2(T) { T genericFunction2() { return T.min; } } toString(genericFunction1!(int)); toString(genericFunction2!(int));
 ..
 ///////////////////////////////////////

 It just looks ugly!

 What about having some kind of anonymous template. (Please correct me if 
 i'm
 wrong)
Do you mean implicit template instantiation? Apparently it'll be in a future version.
 Tom 
Oct 31 2005
parent reply Tomás Rossi <Tomás_member pathlink.com> writes:
In article <dk5min$1h46$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk5lqe$1gar$1 digitaldaemon.com...
 In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template:
If you have a single member in the template, you don't have to.
How is that? You don't have to do it when using the function, but you have to name your template the same as your templated function.
 ///////////////////////////////////////
 template genericFunctions(T)
 {
 T genericFunction1() {return T.max;}
 T genericFunction2() {return T.min;}
 ..
 }

 toString( genericFunctions.genericFunction1!(int)() );
 toString( genericFunctions.genericFunction2!(int)() );
And that could be rewritten as: template genericFunction1(T) { T genericFunction1() { return T.max; } } template genericFunction2(T) { T genericFunction2() { return T.min; } } toString(genericFunction1!(int)); toString(genericFunction2!(int));
 ..
 ///////////////////////////////////////

 It just looks ugly!

 What about having some kind of anonymous template. (Please correct me if 
 i'm
 wrong)
Do you mean implicit template instantiation? Apparently it'll be in a future version.
 Tom 
I was talking about something like this: template (T) { T genericFunction1() {...} T genericFunction2() {...} } Doing: template AAA(T) { T AAA() {...} } template BBB(T) { T BBB() {...} } .. is uglier than C++s: template <class T> T AAA() {...} template <class T> T BBB() {...} .. in the sense that you have to write AAA two times! Tom
Oct 31 2005
parent "John C" <johnch_atms hotmail.com> writes:
If you have a single member in the template, you don't have to.
How is that? You don't have to do it when using the function, but you have to name your template the same as your templated function.
It's to do with templates having their own scope, which makes them akin to modules.
 I was talking about something like this:

 template (T)
 {
 T genericFunction1() {...}
 T genericFunction2() {...}
 }

 Doing:

 template AAA(T) { T AAA() {...} }
 template BBB(T) { T BBB() {...} }
 ..

 is uglier than C++s:

 template <class T> T AAA() {...}
 template <class T> T BBB() {...}
 ..

 in the sense that you have to write AAA two times!
Some here have asked for this requirement to be removed for templated functions.
 Tom 
Oct 31 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:

 In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); } -- Derek Parnell Melbourne, Australia 1/11/2005 8:30:53 AM
Oct 31 2005
parent reply Tomás Rossi <Tomás_member pathlink.com> writes:
In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:

 In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()? Suppose that the language gives you this alternative: template(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } All the above problems are resolved.
-- 
Derek Parnell
Melbourne, Australia
1/11/2005 8:30:53 AM
Hope i had maked my point. Tom BsAs, Argentina PS: Sorry for my poor English.
Oct 31 2005
next sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Tomás Rossi wrote:
 In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
 
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:


In article <dk52us$qpb$1 digitaldaemon.com>, John C says...

"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...

In C++ one could do this:

template <class T>
void genericFunction<T>(someParam1, someParam2, ..., someParamN)
{...generic algorithm...}

and then:

..
genericFunction< list<int> >(blah blah ...);
..

Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ...etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()?
I think I would probably alias the GenericFunctions!(T) part once and use that.
 Suppose that the language gives you this alternative:
 
 template(T)
 {
 void doThis() {...}
 void doThat() {...}
 T getFoo() {...}
 void takeFoo(T t) {...}
 void yourSister() {...}
 void myCousin() {...}
 ...etc...
 }
 
 All the above problems are resolved.
 
And in this case how would you instanciate the template or access any of those functions if the template is anonymous? -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Nov 01 2005
next sibling parent Tomás Rossi <Tomás_member pathlink.com> writes:
In article <dk7d63$2pfk$1 digitaldaemon.com>, Bruno Medeiros says...
Tomás Rossi wrote:
 In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
 
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:


In article <dk52us$qpb$1 digitaldaemon.com>, John C says...

"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...

In C++ one could do this:

template <class T>
void genericFunction<T>(someParam1, someParam2, ..., someParamN)
{...generic algorithm...}

and then:

..
genericFunction< list<int> >(blah blah ...);
..

Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ...etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()?
I think I would probably alias the GenericFunctions!(T) part once and use that.
 Suppose that the language gives you this alternative:
 
 template(T)
 {
 void doThis() {...}
 void doThat() {...}
 T getFoo() {...}
 void takeFoo(T t) {...}
 void yourSister() {...}
 void myCousin() {...}
 ...etc...
 }
 
 All the above problems are resolved.
 
And in this case how would you instanciate the template or access any of those functions if the template is anonymous?
For example: takeFoo!(int)(34); char c = getFoo!(char)(); myCousin!(list!(ulong))(); etc.
-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to 
be... unnatural."
Tom
Nov 01 2005
prev sibling parent reply Oskar Linde <Oskar_member pathlink.com> writes:
In article <dk7d63$2pfk$1 digitaldaemon.com>, Bruno Medeiros says...
Tomás Rossi wrote:
 
 Suppose you have this:
 
 template GenericFunctions(T)
 {
 void doThis() {...}
 void doThat() {...}
 T getFoo() {...}
 void takeFoo(T t) {...}
 void yourSister() {...}
 void myCousin() {...}
 ...etc...
 }
 
 Would you alias one and all?
 Would you write a template with the func. name for everyone? 
 Would you explicitly use GenericFunctions!(T).func()?
 
I think I would probably alias the GenericFunctions!(T) part once and use that.
The with keyword can also be useful for specifying a template instantiation. /Oskar
Nov 01 2005
parent Tomás Rossi <Tomás_member pathlink.com> writes:
In article <dk7hfu$2sud$1 digitaldaemon.com>, Oskar Linde says...
In article <dk7d63$2pfk$1 digitaldaemon.com>, Bruno Medeiros says...
Tomás Rossi wrote:
 
 Suppose you have this:
 
 template GenericFunctions(T)
 {
 void doThis() {...}
 void doThat() {...}
 T getFoo() {...}
 void takeFoo(T t) {...}
 void yourSister() {...}
 void myCousin() {...}
 ...etc...
 }
 
 Would you alias one and all?
 Would you write a template with the func. name for everyone? 
 Would you explicitly use GenericFunctions!(T).func()?
 
I think I would probably alias the GenericFunctions!(T) part once and use that.
The with keyword can also be useful for specifying a template instantiation.
Ok with all those solutions, i'm sure they work fine, but i can't see why there can't be anonymous templates. In fact mixins would do similar job, for example: template Generics(T) { T doThis() {return T.max;} void doThat() {} } void someFunc() { mixin Generics!(int); writefln(toString(doThis())); } but it'd be very nice if i just could do this: template(T) { T doThis() {return T.max;} void doThat() {} } void someFunc() { writefln(toString(doThis!(int)())); }
/Oskar
Tom
Nov 01 2005
prev sibling next sibling parent reply David Medlock <noone nowhere.com> writes:
Tomás Rossi wrote:
 In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
 
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:


In article <dk52us$qpb$1 digitaldaemon.com>, John C says...

"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...

In C++ one could do this:

template <class T>
void genericFunction<T>(someParam1, someParam2, ..., someParamN)
{...generic algorithm...}

and then:

..
genericFunction< list<int> >(blah blah ...);
..

Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()? Suppose that the language gives you this alternative: template(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } All the above problems are resolved.
-- 
Derek Parnell
Melbourne, Australia
1/11/2005 8:30:53 AM
Hope i had maked my point. Tom BsAs, Argentina PS: Sorry for my poor English.
One option is simply to mixin the template: mixin GenericFunctions!(int); then you can simply call the functions you want. doThis(); doThat(); Of course with name clashes(like mixing in the template twice) you will need to use with or alias. -DavidM
Nov 01 2005
parent Tomás Rossi <Tomás_member pathlink.com> writes:
In article <dk7n87$ac$1 digitaldaemon.com>, David Medlock says...
Tomás Rossi wrote:
 In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
 
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:


In article <dk52us$qpb$1 digitaldaemon.com>, John C says...

"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...

In C++ one could do this:

template <class T>
void genericFunction<T>(someParam1, someParam2, ..., someParamN)
{...generic algorithm...}

and then:

..
genericFunction< list<int> >(blah blah ...);
..

Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()? Suppose that the language gives you this alternative: template(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } All the above problems are resolved.
-- 
Derek Parnell
Melbourne, Australia
1/11/2005 8:30:53 AM
Hope i had maked my point. Tom BsAs, Argentina PS: Sorry for my poor English.
One option is simply to mixin the template: mixin GenericFunctions!(int); then you can simply call the functions you want. doThis(); doThat(); Of course with name clashes(like mixing in the template twice) you will need to use with or alias. -DavidM
Yap... i knew that one :) http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/29592 Tom
Nov 01 2005
prev sibling parent reply cpunion gmail.com writes:
In article <dk6p11$28p0$1 digitaldaemon.com>, Tomás Rossi says...
In article <1vo72jbc04tgw.gwxz3kffp4gh.dlg 40tude.net>, Derek Parnell says...
On Mon, 31 Oct 2005 17:55:26 +0000 (UTC), Tomás Rossi wrote:

 In article <dk52us$qpb$1 digitaldaemon.com>, John C says...
"Tomás Rossi" <Tomás_member pathlink.com> wrote in message 
news:dk50a0$mmk$1 digitaldaemon.com...
 In C++ one could do this:

 template <class T>
 void genericFunction<T>(someParam1, someParam2, ..., someParamN)
 {...generic algorithm...}

 and then:

 ..
 genericFunction< list<int> >(blah blah ...);
 ..

 Is this possible in D?
Yes, it's in the documentation http://www.digitalmars.com/d/template.html template genericFunction (T) { void genericFunction(T p1, T p2, ..., T pN) { } } genericFunction!(list!(int))(...);
 Tom 
Ok, I read the docs but the syntax was not so clear to me. Anyway, the C++ syntax (not referring about <>) is a lot better in the sense that you are not bound to name your template: /////////////////////////////////////// template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} .. } toString( genericFunctions.genericFunction1!(int)() ); toString( genericFunctions.genericFunction2!(int)() ); .. /////////////////////////////////////// It just looks ugly!
Yes it does. However Walter's suggested solution is to use the 'alias' declaration. template genericFunctions(T) { T genericFunction1() {return T.max;} T genericFunction2() {return T.min;} } // Define some easier names to type and read. alias genericFunctions!(int).genericFunction1 gf1; alias genericFunctions!(int).genericFunction2 gf2; // Show them in use. void main() { gf1(); gf2(); }
The same shit with different color would say my grandfather. :) That solution is a little ugly also and very old fashioned. Since D proclaims to be the cure for mosts of C++ syntax diseases (well, this is what i got at least), i can't see why do i have to appeal to this kind of "C++ style" workarounds. Besides, i don't see (and correct me please in other case) a good reason to dismiss a more elegant solution (builded in the language itself, like other similar problematics were faced), at least in some distant future. Suppose you have this: template GenericFunctions(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } Would you alias one and all? Would you write a template with the func. name for everyone? Would you explicitly use GenericFunctions!(T).func()? Suppose that the language gives you this alternative: template(T) { void doThis() {...} void doThat() {...} T getFoo() {...} void takeFoo(T t) {...} void yourSister() {...} void myCousin() {...} ..etc... } All the above problems are resolved.
-- 
Derek Parnell
Melbourne, Australia
1/11/2005 8:30:53 AM
Hope i had maked my point. Tom BsAs, Argentina PS: Sorry for my poor English.
Delegate!(void delegate()) dele; dele += obj.func; dele += obj.func1; dele (); Delegate!(void delegate(char[], int, float, short, .......)) dele1; dele1 += obj.funca; dele1 += obj.funca1; dele1 (.........); I think that is difficult. In C++, I can do this: void test(int, int); void test1(short, short); Delegate<void(short, char)> dele; dele += test; dele += test1; The function "operator +=" is a template function, it can deduct the types of arguments, then I can use the types and process them. Of course, that need to use template specialization, it depends on the count of function arguments. In D, I don't know how to do it. PS: Sorry for my poor English too.
Nov 04 2005
parent reply "John C" <johnch_atms hotmail.com> writes:


 Delegate!(void delegate()) dele;
 dele += obj.func;
 dele += obj.func1;
 dele ();

 Delegate!(void delegate(char[], int, float, short, .......)) dele1;
 dele1 += obj.funca;
 dele1 += obj.funca1;
 dele1 (.........);

 I think that is difficult.

 In C++, I can do this:

 void test(int, int);
 void test1(short, short);
 Delegate<void(short, char)> dele;
 dele += test;
 dele += test1;

 The function "operator +=" is a template function, it can deduct the types 
 of
 arguments, then I can use the types and process them.
 Of course, that need to use template specialization, it depends on the 
 count of
 function arguments.

 In D, I don't know how to do it.

 PS: Sorry for my poor English too.
There's a few so-called multicast delegate libraries floating around. MinWin contains a good implementation http://home.comcast.net/~benhinkle/minwin/. There are also some signal/slot libraries, for example at http://www.uwesalomon.de/code/indigo/files2/index-txt.html. If you need the overloaded += behaviour, I've pasted my own version, which extends MinWin's, below. To declare a multicast delegate: alias MulticastDelegate!(void, char[]) StringDisplayHandler; To use it: void stringDisplayFunc(char[] s) { writefln(s); } StringDisplayHandler handler; handler += delegate void(char[] s) { writefln(s); }; handler += &stringDisplayFunc; handler("Hello World"); Source: template MethodWrapperBase(TDelegate, TFunction) { public bool isStatic; package union { TDelegate delegate_; struct { void* p; TFunction function_; } } public static MethodWrapper wrap(TDelegate d) { MethodWrapper m; m.delegate_ = d; return m; } public static MethodWrapper wrap(TFunction f) { MethodWrapper m; m.isStatic = true; m.function_ = f; return m; } void clear() { function_ = null; delegate_ = null; } } struct MethodWrapper(R) { alias R delegate() TDelegate; alias R function() TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall() { if (isStatic) { if (function_ != null) return function_(); return R.init; } if (delegate_ != null) return delegate_(); return R.init; } } struct MethodWrapper(R : void) { alias R delegate() TDelegate; alias R function() TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall() { if (isStatic) { if (function_ != null) function_(); } if (delegate_ != null) delegate_(); } } struct MethodWrapper(R, T) { alias R delegate(T) TDelegate; alias R function(T) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T arg) { if (isStatic) { if (function_ != null) return function_(arg); return R.init; } if (delegate_ != null) return delegate_(arg); return R.init; } } struct MethodWrapper(R : void, T) { alias R delegate(T) TDelegate; alias R function(T) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T arg) { if (isStatic) { if (function_ != null) function_(arg); } if (delegate_ != null) delegate_(arg); } } struct MethodWrapper(R, T0, T1) { alias R delegate(T0, T1) TDelegate; alias R function(T0, T1) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1) { if (isStatic) { if (function_ != null) return function_(arg0, arg1); return R.init; } if (delegate_ != null) return delegate_(arg0, arg1); return R.init; } } struct MethodWrapper(R : void, T0, T1) { alias R delegate(T0, T1) TDelegate; alias R function(T0, T1) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1) { if (isStatic) { if (function_ != null) function_(arg0, arg1); } if (delegate_ != null) delegate_(arg0, arg1); } } struct MethodWrapper(R, T0, T1, T2) { alias R delegate(T0, T1, T2) TDelegate; alias R function(T0, T1, T2) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2) { if (isStatic) { if (function_ != null) return function_(arg0, arg1, arg2); return R.init; } if (delegate_ != null) return delegate_(arg0, arg1, arg2); return R.init; } } struct MethodWrapper(R : void, T0, T1, T2) { alias R delegate(T0, T1, T2) TDelegate; alias R function(T0, T1, T2) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2) { if (isStatic) { if (function_ != null) function_(arg0, arg1, arg2); } if (delegate_ != null) delegate_(arg0, arg1, arg2); } } struct MethodWrapper(R, T0, T1, T2, T3) { alias R delegate(T0, T1, T2, T3) TDelegate; alias R function(T0, T1, T2, T3) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3) { if (isStatic) { if (function_ != null) return function_(arg0, arg1, arg2, arg3); return R.init; } if (delegate_ != null) return delegate_(arg0, arg1, arg2, arg3); return R.init; } } struct MethodWrapper(R : void, T0, T1, T2, T3) { alias R delegate(T0, T1, T2, T3) TDelegate; alias R function(T0, T1, T2, T3) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3) { if (isStatic) { if (function_ != null) function_(arg0, arg1, arg2, arg3); } if (delegate_ != null) delegate_(arg0, arg1, arg2, arg3); } } struct MethodWrapper(R, T0, T1, T2, T3, T4) { alias R delegate(T0, T1, T2, T3, T4) TDelegate; alias R function(T0, T1, T2, T3, T4) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { if (isStatic) { if (function_ != null) return function_(arg0, arg1, arg2, arg3, arg4); return R.init; } if (delegate_ != null) return delegate_(arg0, arg1, arg2, arg3, arg4); return R.init; } } struct MethodWrapper(R : void, T0, T1, T2, T3, T4) { alias R delegate(T0, T1, T2, T3, T4) TDelegate; alias R function(T0, T1, T2, T3, T4) TFunction; mixin MethodWrapperBase!(TDelegate, TFunction); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { if (isStatic) { if (function_ != null) function_(arg0, arg1, arg2, arg3, arg4); } if (delegate_ != null) delegate_(arg0, arg1, arg2, arg3, arg4); } } template MulticastDelegateBase() { public void add(TDelegate d) { if (d == null) return; int len = methods_.length; int n = len - 1; while (n >= 0 && methods_[n].delegate_ == null) --n; if (n < len - 1) methods_[n + 1] = TMethodWrapper.wrap(d); else methods_ ~= TMethodWrapper.wrap(d); } public void opAddAssign(TDelegate d) { add(d); } public void remove(TDelegate d) { if (methods_.length == 0) return; bool found; for (int i = 0; i < methods_.length - 1; ++i) { if (!found && methods_[i].delegate_ is d) found = true; if (found) methods_[i] = methods_[i + 1]; if (methods_[i].delegate_ is null) break; } if (found || methods_[length - 1].delegate_ is d) methods_[length - 1].clear(); } public void opSubAssign(TDelegate d) { remove(d); } public void remove(TFunction f) { if (methods_.length == 0) return; bool found; for (int i = 0; i < methods_.length - 1; ++i) { if (!found && methods_[i].function_ is f) found = true; if (found) methods_[i] = methods_[i + 1]; if (methods_[i].delegate_ is null) break; } if (found || methods_[length - 1].function_ is f) methods_[length - 1].clear(); } public void opSubAssign(TFunction f) { remove(f); } public bool isEmpty() { if (methods_.length == 0) return true; else if (methods_[0].delegate_ == null) return true; return false; } } template MulticastDelegateGenericMixins() { alias TMethodWrapper.TDelegate TDelegate; alias TMethodWrapper.TFunction TFunction; package TMethodWrapper[] methods_; mixin MulticastDelegateBase; } template MulticastDelegateMixins(R) { alias MethodWrapper!(R) TMethodWrapper; mixin MulticastDelegateGenericMixins; } template MulticastDelegateMixins(R, T) { alias MethodWrapper!(R, T) TMethodWrapper; mixin MulticastDelegateGenericMixins; } template MulticastDelegateMixins(R, T0, T1) { alias MethodWrapper!(R, T0, T1) TMethodWrapper; mixin MulticastDelegateGenericMixins; } template MulticastDelegateMixins(R, T0, T1, T2) { alias MethodWrapper!(R, T0, T1, T2) TMethodWrapper; mixin MulticastDelegateGenericMixins; } template MulticastDelegateMixins(R, T0, T1, T2, T3) { alias MethodWrapper!(R, T0, T1, T2, T3) TMethodWrapper; mixin MulticastDelegateGenericMixins; } template MulticastDelegateMixins(R, T0, T1, T2, T3, T4) { alias MethodWrapper!(R, T0, T1, T2, T3, T4) TMethodWrapper; mixin MulticastDelegateGenericMixins; } struct MulticastDelegate(R) { mixin MulticastDelegateMixins!(R); public R opCall() { for (int i = 0; i < methods_.length - 1; i++) methods_[i](); return methods_[$ - 1](); } } struct MulticastDelegate(R : void) { mixin MulticastDelegateMixins!(R); public R opCall() { foreach (TMethodWrapper method; methods_) method(); } } struct MulticastDelegate(R, T) { mixin MulticastDelegateMixins!(R, T); public R opCall(T arg) { for (int i = 0; i < methods_.length - 1; i++) methods_[i](arg); return methods_[$ - 1](arg); } } struct MulticastDelegate(R : void, T) { mixin MulticastDelegateMixins!(R, T); public R opCall(T arg) { foreach (TMethodWrapper method; methods_) method(arg); } } struct MulticastDelegate(R, T0, T1) { mixin MulticastDelegateMixins!(R, T0, T1); public R opCall(T0 arg0, T1 arg1) { for (int i = 0; i < methods_.length - 1; i++) methods_[i](arg0, arg1); return methods_[$ - 1](arg0, arg1); } } struct MulticastDelegate(R : void, T0, T1) { mixin MulticastDelegateMixins!(R, T0, T1); public R opCall(T0 arg0, T1 arg1) { foreach (TMethodWrapper method; methods_) method(arg0, arg1); } } struct MulticastDelegate(R, T0, T1, T2) { mixin MulticastDelegateMixins!(R, T0, T1, T2); public R opCall(T0 arg0, T1 arg1, T2 arg2) { for (int i = 0; i < methods_.length - 1; i++) methods_[i](arg0, arg1, arg2); return methods_[$ - 1](arg0, arg1, arg2); } } struct MulticastDelegate(R : void, T0, T1, T2) { mixin MulticastDelegateMixins!(R, T0, T1, T2); public R opCall(T0 arg0, T1 arg1, T2 arg2) { foreach (TMethodWrapper method; methods_) method(arg0, arg1, arg2); } } struct MulticastDelegate(R, T0, T1, T2, T3) { mixin MulticastDelegateMixins!(R, T0, T1, T2, T3); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3) { for (int i = 0; i < methods_.length - 1; i++) methods_[i](arg0, arg1, arg2, arg3); return methods_[$ - 1](arg0, arg1, arg2, arg3); } } struct MulticastDelegate(R : void, T0, T1, T2, T3) { mixin MulticastDelegateMixins!(R, T0, T1, T2, T3); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3) { foreach (TMethodWrapper method; methods_) method(arg0, arg1, arg2, arg3); } } struct MulticastDelegate(R, T0, T1, T2, T3, T4) { mixin MulticastDelegateMixins!(R, T0, T1, T2, T3, T4); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { for (int i = 0; i < methods_.length - 1; i++) methods_[i](arg0, arg1, arg2, arg3, arg4); return methods_[$ - 1](arg0, arg1, arg2, arg3, arg4); } } struct MulticastDelegate(R : void, T0, T1, T2, T3, T4) { mixin MulticastDelegateMixins!(R, T0, T1, T2, T3, T4); public R opCall(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { foreach (TMethodWrapper method; methods_) method(arg0, arg1, arg2, arg3, arg4); } }
Nov 04 2005
parent reply cpunion gmail.com writes:
In article <dkgd5c$2o1d$1 digitaldaemon.com>, John C says...
There's a few so-called multicast delegate libraries floating around. MinWin 
contains a good implementation http://home.comcast.net/~benhinkle/minwin/. 
There are also some signal/slot libraries, for example at 
http://www.uwesalomon.de/code/indigo/files2/index-txt.html.

If you need the overloaded += behaviour, I've pasted my own version, which 
extends MinWin's, below.

To declare a multicast delegate:

    alias MulticastDelegate!(void, char[]) StringDisplayHandler;

To use it:

    void stringDisplayFunc(char[] s) {
        writefln(s);
    }

    StringDisplayHandler handler;
    handler += delegate void(char[] s) {
        writefln(s);
    };
    handler += &stringDisplayFunc;
    handler("Hello World");
Thanks. It works well!
Nov 04 2005
parent reply cpunion gmail.com writes:
In article <dkgtg6$4qr$1 digitaldaemon.com>, cpunion gmail.com says...
In article <dkgd5c$2o1d$1 digitaldaemon.com>, John C says...
There's a few so-called multicast delegate libraries floating around. MinWin 
contains a good implementation http://home.comcast.net/~benhinkle/minwin/. 
There are also some signal/slot libraries, for example at 
http://www.uwesalomon.de/code/indigo/files2/index-txt.html.

If you need the overloaded += behaviour, I've pasted my own version, which 
extends MinWin's, below.

To declare a multicast delegate:

    alias MulticastDelegate!(void, char[]) StringDisplayHandler;

To use it:

    void stringDisplayFunc(char[] s) {
        writefln(s);
    }

    StringDisplayHandler handler;
    handler += delegate void(char[] s) {
        writefln(s);
    };
    handler += &stringDisplayFunc;
    handler("Hello World");
Thanks. It works well!
The Boost::function can accept the compatible types, for example: int f1(int); // function type: int(int) short f2(double); // function type: short(double) struct functor // functor type: int(int) { int operator()(double){} }; functor f3; // functor object boost::function<int(int)> func; // function object, lick delegate, type: int(int) func = f1; // can accept int(int) func = f2; // can accept short(double) func = f3; // can accept functor(type: int(double)). In D, may be replaced with &f3.opCall? The function object can accept the compatible types, can resolve it in D? Thanks.
Nov 04 2005
parent reply "John C" <johnch_atms hotmail.com> writes:
<cpunion gmail.com> wrote in message news:dkhcob$gaa$1 digitaldaemon.com...
 In article <dkgtg6$4qr$1 digitaldaemon.com>, cpunion gmail.com says...
In article <dkgd5c$2o1d$1 digitaldaemon.com>, John C says...
There's a few so-called multicast delegate libraries floating around. 
MinWin
contains a good implementation 
http://home.comcast.net/~benhinkle/minwin/.
There are also some signal/slot libraries, for example at
http://www.uwesalomon.de/code/indigo/files2/index-txt.html.

If you need the overloaded += behaviour, I've pasted my own version, 
which
extends MinWin's, below.

To declare a multicast delegate:

    alias MulticastDelegate!(void, char[]) StringDisplayHandler;

To use it:

    void stringDisplayFunc(char[] s) {
        writefln(s);
    }

    StringDisplayHandler handler;
    handler += delegate void(char[] s) {
        writefln(s);
    };
    handler += &stringDisplayFunc;
    handler("Hello World");
Thanks. It works well!
The Boost::function can accept the compatible types, for example: int f1(int); // function type: int(int) short f2(double); // function type: short(double) struct functor // functor type: int(int) { int operator()(double){} }; functor f3; // functor object boost::function<int(int)> func; // function object, lick delegate, type: int(int) func = f1; // can accept int(int) func = f2; // can accept short(double) func = f3; // can accept functor(type: int(double)). In D, may be replaced with &f3.opCall? The function object can accept the compatible types, can resolve it in D? Thanks.
That's doubtful. I've not even seen functors in use in D like that, so don't think it's possible.
Nov 05 2005
parent cpunion gmail.com writes:
In article <dkhtuh$1432$1 digitaldaemon.com>, John C says...
That's doubtful. I've not even seen functors in use in D like that, so don't 
think it's possible. 
Thanks. I think that not need that in D. :-)
Nov 05 2005