digitalmars.D.learn - How to declare a template type as parameter to functions
- Domingo (27/27) Nov 03 2014 Hello !
- Domingo (42/42) Nov 03 2014 One of the problems I'm facing from vibed (but I'm asking a
- H. S. Teoh via Digitalmars-d-learn (43/61) Nov 03 2014 Use the typeof operator, for example:
- Domingo (19/19) Nov 03 2014 Thanks for the answer !
- Domingo (21/21) Nov 03 2014 Now I realize that what I said on the previous post is not
- H. S. Teoh via Digitalmars-d-learn (46/62) Nov 03 2014 T is a placeholder identifier that can be any accepted type. For
- Domingo (10/10) Nov 03 2014 Thanks again this second explanation now is easier to understand
- H. S. Teoh via Digitalmars-d-learn (13/26) Nov 03 2014 [...]
Hello ! I could not find a clear way that show how to use template types as parameter to functions: There is a general rule to do it ? On several examples when the return type comes from a template I saw the usage of "auto" where the compiler will deduce the correct type but when we need to pass that value as a parameter to a function how we declare then as parameter ? //void dummFunction(type<Bson,Bson,Bson> "appender", type<forFromAuto> "another templated type") void dummFunction(typeforFromAuto "appender", typeforFromAuto "another templated type") { } auto as = appender!string(); auto an = appender!double(); auto an = appender!customType(); auto bd = collection.find().limit(2); struct MongoCursor(Q = Bson, R = Bson, S = Bson); auto bd2 = collection.find(Bson(["key": Bson(3)])).limit(2); auto bd3 = collection.find(Bson(["key": Bson(3)]), ["fld":1, "data":1]).limit(2); The above example is dummy example only imagine that you need to write a function accepting one of the several templated types returned on several parts of phobos and third party libraries like vibed. Can someone give a general rule for this kind of problem ?
Nov 03 2014
One of the problems I'm facing from vibed (but I'm asking a general rule to help here and in other similar cases): protected void sendCollectionListAsDataArrayJson2(MongoCursor!(Bson,Bson,Bson) collection_list, HTTPServerResponse res) { if(!collection_list.empty) { auto buf = appender!string(); buf.put("{\"data\":[\n"); int count = 0; foreach(doc; collection_list) { if(count++ > 0) { buf.put(","); } buf.put("["); buf.put(doc.toJson().toString()); buf.put("]\n"); } buf.put("]}\n"); res.writeBody(buf.data, "application/json"); } } ------- ../../dLib/inhouse-code/vibed_common.d(313): Error: function vibed_common.BaseHttpHandler.sendCollectionListAsDataArrayJson2 (MongoCursor!(Bson, Bson, Bson) collection_list, HTTPServerResponse res) is not callable using argument types (MongoCursor!(Bson, Bson, typeof(null)), HTTPServerResponse) ../ApakauAdminCommon/vibed/geoips_mixin.d(38): Error: function vibed_common.BaseHttpHandler.sendCollectionListAsDataArrayJson2 (MongoCursor!(Bson, Bson, Bson) collection_list, HTTPServerResponse res) is not callable using argument types (MongoCursor!(Bson, Bson, int[string]), HTTPServerResponse) ../ApakauAdminCommon/vibed/geoips_mixin.d(50): Error: function vibed_common.BaseHttpHandler.sendCollectionListAsDataArrayJson2 (MongoCursor!(Bson, Bson, Bson) collection_list, HTTPServerResponse res) is not callable using argument types (MongoCursor!(Bson, Bson, int[string]), HTTPServerResponse)
Nov 03 2014
On Mon, Nov 03, 2014 at 11:43:42PM +0000, Domingo via Digitalmars-d-learn wrote:Hello ! I could not find a clear way that show how to use template types as parameter to functions: There is a general rule to do it ? On several examples when the return type comes from a template I saw the usage of "auto" where the compiler will deduce the correct type but when we need to pass that value as a parameter to a function how we declare then as parameter ? //void dummFunction(type<Bson,Bson,Bson> "appender", type<forFromAuto> "another templated type") void dummFunction(typeforFromAuto "appender", typeforFromAuto "another templated type") { }Use the typeof operator, for example: auto myfunc(...) { struct InternalType { ... } ... return InternalType(...); } void anotherFunc(typeof(myfunc(...)) x) { ... } void main() { auto x = myfunc(...); anotherFunc(x); } Using typeof() everywhere is ugly, though, so you could abstract it away with an alias: auto myfunc(...) { ... } alias MyType = typeof(myfunc(...)); void anotherFunc(MyType x) { ... } ... On the other hand, if anotherFunc() doesn't really need to know what exact type is passed, you could turn it into a template function: auto myfunc(...) { ... } // Now you can pass anything to anotherFunc: void anotherFunc(T)(T x) { ... } But passing "anything" may cause problems, if anotherFunc expects x to have certain methods, but it's not guaranteed to have them: void anotherFunc(T)(T x) { ... x.method(); // will fail if T is int, for example ... } In this case you can use a signature constraint to limit the scope of what anotherFunc will accept: auto myfunc(...) { ... } void anotherFunc(T)(T x) if (is(T.init.method())) // test that T has a method called "method" { ... x.method(); ... } T -- Being able to learn is a great learning; being able to unlearn is a greater learning.
Nov 03 2014
Thanks for the answer ! But then I can see that using D style templates everywhere will prevent write generic code and what seems to be an innocent function call will explode to bloated mass of code. Like the "simple" function that I tried to write to not duplicate code is not worth because I'll need to write one for each type of MongoCursor: 1 - MongoCursor!(Bson, Bson, typeof(null)) 2 - MongoCursor!(Bson, Bson, Bson) 3 - MongoCursor!(Bson, Bson, int[string]) protected void sendCollectionListAsDataArrayJson2(T)(T collection_list, HTTPServerResponse res) What will be "T" on the function above ? If I need to write one for each of then My intent of prevent duplicated code is dead. The function only use code that should work on any combination of MongoCursor template. To write less code I'll end up writing more code ? Or are we missing something else here ?
Nov 03 2014
Now I realize that what I said on the previous post is not correct. Based on the proposed use of typeof/alias we will need something like this: alias MongoCurosr3NUll = MongoCursor!(Bson, Bson, typeof(null)); alias MongoCursor3Bson = MongoCursor!(Bson, Bson, Bson); alias MongoCursor3IntStr = MongoCursor!(Bson, Bson, int[string]); then call my function like this: sendCollectionListAsDataArrayJson2!MongoCurosr3NUll( MongoCurosr3NUllParam, res); sendCollectionListAsDataArrayJson2!MongoCursor3Bson( MongoCursor3BsonParam, res); sendCollectionListAsDataArrayJson2!MongoCursor3IntStr( MongoCursor3IntStrParam, res); I do not think this way of writing code is "DRY" or easy to write/read/understand, it seems that D code will end up been a crypt one a la "perl" !!! No offense here to perl but some write code style used on it. !!!!! Please help here to make this clear for me and future D language users !!!!!!! Cheers !
Nov 03 2014
On Tue, Nov 04, 2014 at 12:29:54AM +0000, Domingo via Digitalmars-d-learn wrote: [...]Like the "simple" function that I tried to write to not duplicate code is not worth because I'll need to write one for each type of MongoCursor: 1 - MongoCursor!(Bson, Bson, typeof(null)) 2 - MongoCursor!(Bson, Bson, Bson) 3 - MongoCursor!(Bson, Bson, int[string]) protected void sendCollectionListAsDataArrayJson2(T)(T collection_list, HTTPServerResponse res) What will be "T" on the function above ?T is a placeholder identifier that can be any accepted type. For example: // Note: only one copy of func needs to be written void func(T)(T x) { writeln("%s", x); } void main() { func(1); // you can pass an int func("x"); // or a string func(1.0); // or a float struct S {} S s; func(s); // or a struct }If I need to write one for each of then My intent of prevent duplicated code is dead. The function only use code that should work on any combination of MongoCursor template.That's exactly what you need a template function for. Instead of writing 15 copies of the function, one for each different MongoCursor type, you write only a single function that takes a generic parameter, for example: void sendCollection(T)(MongoCursor!(Bson, Bson, T) list, HttpRequest req) { ... } ... HttpRequest req; MongoCursor!(Bson, Bson, int) x1; MongoCursor!(Bson, Bson, float) x2; MongoCursor!(Bson, Bson, int[string]) x3; // N.B.: you can pass any matching type sendCollection(x1, req); sendCollection(x2, req); sendCollection(x3, req); Of course, the foregoing assumes that only the last parameter of MongoCursor varies. If you need to take MongoCursor of *any* combination of parameters, you can use multiple template parameters, e.g.: // Now this will work with MongoCursor!(Bson, Bson, // int[string]), MongoCursor!(Json, Bson, Bson), // MongoCursor!(string, int, float), etc.. void sendCollection(T,U,V)(MongoCursor!(T,U,V) list, ...) { ... } T -- Those who don't understand D are condemned to reinvent it, poorly. -- Daniel N
Nov 03 2014
Thanks again this second explanation now is easier to understand as general rule for this case and future ones that I'll face in the future. I hope that this explanation would be added to the language reference where it explain functions: http://dlang.org/function With it there people will have a better understand right from the fundamental source of information. Can someone add it there ? Cheers !
Nov 03 2014
On Tue, Nov 04, 2014 at 12:48:47AM +0000, Domingo via Digitalmars-d-learn wrote:Thanks again this second explanation now is easier to understand as general rule for this case and future ones that I'll face in the future. I hope that this explanation would be added to the language reference where it explain functions: http://dlang.org/function With it there people will have a better understand right from the fundamental source of information. Can someone add it there ?[...] Wow, I can't believe that page doesn't even *mention* template functions except in a single sentence! Please file a bug on issues.dlang.org to improve the documentation of template functions. In the meantime, the language reference really isn't the best source for learning the language; Ali's excellent D book is better: http://ddili.org/ders/d.en/templates.html Andrei's book "The D Programming Language" is also highly recommended. T -- "Outlook not so good." That magic 8-ball knows everything! I'll ask about Exchange Server next. -- (Stolen from the net)
Nov 03 2014
Thanks again the bug issue is there at https://issues.dlang.org/show_bug.cgi?id=13677 But probably I should fork the repository and fix myself !
Nov 03 2014
Here is my pull request https://github.com/D-Programming-Language/dlang.org/pull/690 Please anyone feel free to improve it. Cheers !
Nov 03 2014