August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to anderson | On Thu, 22 Aug 2002 18:45:44 +0800 "anderson" <anderson@firestar.com.au> wrote:
> I was wondering about this syntax sugar.
>
> //Where foo is an template
> import foo(int);
>
> Then you could use all the methods like C functions.
>
> x = Max(a,b);
>
> Ofcourse problems would occur when there are more then one...
>
> import foo(int);
> import foo(float);
>
> But the complier could work that out.
Yes, just as if the function was overloaded (and any clashes like foo(int)
declared
twice are considered errors). I like this!
|
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to anderson | (The following message represents me thinking and typing at the same time. It thus flows along my stream of consciousness, and my opinions change as it progresses. Please read the entire post before replying...) Since 'import' already has a meaning, and since D templates do share many features in common with namespaces, would 'using' be a better keyword? using foo(int); or, to be more complete and provide more flexibility: using template foo(int); // moves all template members into current namespace using foo(int).Max; // only moves Max into current namespace If you attempted to bring in entire multiple instantiations of the same template, that could probably just be outlawed. Since you would have to do the equivalent of a scope resolution at every usage to tell the compiler what to do (since *all* of the names would have collided), you might as well have just done that and skipped the 'using' step. If you brought in different pieces of the same template, but from different instantiations: using foo(int).Max; using foo(double).Min; then there would be no namespace collision, and it might be allowable. Horribly confusing, in the example given above, but possibly useful in some situations... Overall, I think that the 'using template foo(int);' form would be a handy addition for people who only needed a single instantiation of the template and didn't want to have to precede every template member usage with 'intfoo.'. Trying to extend the usage beyond that, however, causes more problems than it solves. Which leads me to my favorite solution so far, and it is even already in the language (at least in the syntax, even if the template usage of it may not be in the compiler yet) -- 'with'! with foo(int) { x = Max(a,b); // more stuff, obviously } or maybe: with inst foo(int) { } or: inst foo(int) intfoo; with intfoo { } This saves adding another template specific keyword, explains how name collisions will be resolved (innermost 'with' clause that contains such a member will win), and just generally seems nice and clean to me... That may be my Visual Basic experience coming back to me (VB also uses 'with', and you use it a LOT when you start getting OOPed in VB). Mac In article <ak2f15$179g$1@digitaldaemon.com>, anderson says... > >Wow, one day since this was posted and all these emails. > >I was wondering about this syntax sugar. > > //Where foo is an template > import foo(int); > >Then you could use all the methods like C functions. > > x = Max(a,b); > >Ofcourse problems would occur when there are more then one... > > import foo(int); > import foo(float); > >But the complier could work that out. > >"Walter" <walter@digitalmars.com> wrote in message news:ajvgsb$6gt$1@digitaldaemon.com... >> www.digitalmars.com/template.html >> >> Notice how short it is <g>. Ok, what did I miss? >> >> > > |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | What about this... template Foo(this : T) // use this to bind it to a class { int addClassFunc(int a) { return this.localFunc() + a; } } class Bar { in Foo(Bar) mixin; int localFunc() { return 12; } } |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | No, I haven't. But perhaps it can be done with interfaces. "Patrick Down" <pat@codemoon.com> wrote in message news:Xns927255B703EE3patcodemooncom@63.105.9.61... > Have you see C++ template usage like this? > > template<class T> > class Foo > { > public: > int addToClassFunc(int param) > { > T* pT = static_cast<T*>(this); > > return pT->classFunc() + param; > } > } > > class Bar : public A, public Foo<Bar> > { > int classFunc() > { > return 12; > } > }; > > Bar b; > b.addToClassFunc(5); // return 15 > > > Of course D doesn't have multiple inheritance. > But do you really need it to be able to do > functionality aggregation like the C++ example > above? |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Juan Carlos Arevalo Baeza | Minor semantic point, but the more general case of smart resource managers has begun to be named "smart handles". Since pointers are inextricably tied up with memory in so many developers minds, a change in name (while technically irrelevant) helps us to remember non-memory resources like files, mutexes, ports, etc. This has been a major contention with garbage collected systems for one of my coworkers. My current stance is that garbage collection solves the 99% rule with 1% of the effort. Because D is a pragmatic language, rather than an academic one, it also supplies two important resource management capabilities: 1. explicit delete 2. finally clauses Most garbage collected systems refuse to allow *any* way to guarantee when an object will be freed/finalized. Explicit deletes at least allow you as much control as you had in C. It does not provide the automatic scoping destructor behavior, however, so you have to use 'finally' clauses. If you have a resource that you absolutely have to clear up before you exit a scope, build a finally clause and clean it up in there. This does take a bit more effort, but only for the rarer case of non-memory resources, which you generally end up writing a lot of exception handling code for anyway. Non-memory resources are *much* more likely to be inaccessible, or to exhibit some form of error or other exception while you are using them, so you have to be careful with them no matter how much support the language provides. The addition of a finally clause to a scope that is already laden with error handling code is not too much of a price to pay, and actually substantially decreases the programming load from most code that I have seen. Having said all of that, it would be nice to have the ability to have a reference counted object. I would not want it for all objects, because the speed penalty of reference counting *all* of your pointers is rather severe (Nothing like a big heavy book on Garbage Collection to clear out any misconceptions you have...). However, for specific things, like files, mutex locks, ports, etc, it might be nice to have a syntax like: counted class SerialPort { } This would cause the compiler to add a thread-safe reference counting mechanism to SerialPort. Creation, assignment, etc would then have to maintain the reference count invariant and delete the object as soon as the reference count hit 0. It does add special handling to objects of this type, as well as references/pointers to this type, but I don't think it causes any problems for separate lexing/parsing. I think it just requires that the code generator be able to access the symbol table to know that this object is counted, and the code generator has to have access to the symbol table anyway... For basic "allocation is acquisition" style programming, this works great. Reference comes into being at top of scope, resource is acquired in constructor and ref count goes up to 1. At the bottom of the scope, the reference disappears, the ref count goes down to 0, and the object is deleted, just like it would have been in C++. What's really nice is that you can make the thing inside a function and return it back out. The process of copying the pointer/reference into the return value increases the reference count. The object will live as long as anyone is using it, and die the instant the last user lets go. Reference counting is notoriously difficult to do in libraries or source code, because the compiler can perform optimizations around scope boundaries that can invalidate the reference counting invariant. If that ever happens, the whole scheme explodes (you either leak something or free it too soon). But if the compiler did the reference counting, it could ensure logically correct reference counting, even if it took shortcuts for efficiency. For example, if a local object was being returned, the compiler knows that one reference existed inside the function and that one reference will exist outside the function. Technically, it should increase the reference when it copies the pointer into the return value, and then decrease the reference when it unrolls the stack and loses the local variable. However, it could simply not touch the reference count at all, and be completely correct in its result. It would know this because it was trading 1 local reference for 1 return reference. A similar behavior occurs at the point where the return value for the function is assigned into a variable, and the same optimization can be performed. By providing a selective ability to use reference counted classes, and by making it require the extra keyword, D could provide additional flexibility without adding danger to the new users. Until you were experienced enough to know what 'counted' was for and why you would want to use it, you would simply leave all your classes GC'ed, which is logically correct, even if it might introduce longer pauses before resources were freed. You *don't* want to go to all reference counted classes, because the speed penalties are bad, and more importantly, because reference counting cannot remove cyclic systems. A.next = B; B.next = C; C.next = B; // made a loop with B and C // do something A.next = NULL; // No way to reach B or C, but each still has a reference count of 1 // because of the loop. Mark and sweep, which D currently uses, has absolutely no problem whatsoever with cyclic systems, and (depending on the implementation of the algorithm) can provide more tunable memory management CPU consumption than reference counting. That makes GC a much better general purpose solution than refcounting. Sorry, that was more rambling than I intended, and probably more than this audience needed... Mac In article <ak1ht1$753$1@digitaldaemon.com>, Juan Carlos Arevalo Baeza says... > >"Walter" <walter@digitalmars.com> wrote in message news:ak147n$273f$1@digitaldaemon.com... > >> In a garbage collected language, is there a need for smart pointers? > > Butofcourse. Smart pointers and memory management don't necessarily have >to be related at all. The fact that most smart pointers are only used to manage memory doesn't mean that has to be the case. For example, I have a buncha smart pointers that manage file access. They are "smart" because they will manage the ownership of the file, and "pointers" because they emulate a pointer to an interface with members that perform operations on the file. > > The way you have D set up, you just can't do this, anyway, which I still >think is a real pity and the thing that kills D (alongside with Java) for me. Ahem... Not that I'm not duly impressed... > >Salutaciones, > JCAB > > > |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <walter@digitalmars.com> wrote in news:ak2umn$1qcd$1 @digitaldaemon.com:
> No, I haven't. But perhaps it can be done with interfaces.
>
It's used extensivly by microsoft in ATL. It's one of those C++ this where I find the C++ template syntax bad, but the general idea has merit.
|
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Patrick Down | Offhand I don't see why that shouldn't work. -Walter "Patrick Down" <pat@codemoon.com> wrote in message news:Xns927264FD45DF2patcodemooncom@63.105.9.61... > > What about this... > > template Foo(this : T) // use this to bind it to a class > { > int addClassFunc(int a) > { > return this.localFunc() + a; > } > } > > class Bar > { > in Foo(Bar) mixin; > > int localFunc() > { > return 12; > } > } > > > > > |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mac Reiter | Your comments on smart handles in D explain it better than I have. Mind if I plagairize it a bit? I also suspect you are right in that the only way to do reference counting right is to clue the compiler in and have the compiler manage it. |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mac Reiter | I hadn't thought of using the with, but it just might be the ticket. And no, it doesn't work yet with templates because templates aren't implemented at all :-( in the compiler. "Mac Reiter" <Mac_member@pathlink.com> wrote in message news:ak2tg7$1p28$1@digitaldaemon.com... > (The following message represents me thinking and typing at the same time. It > thus flows along my stream of consciousness, and my opinions change as it progresses. Please read the entire post before replying...) > > Since 'import' already has a meaning, and since D templates do share many features in common with namespaces, would 'using' be a better keyword? > > using foo(int); > > or, to be more complete and provide more flexibility: > > using template foo(int); // moves all template members into current namespace > using foo(int).Max; // only moves Max into current namespace > > If you attempted to bring in entire multiple instantiations of the same template, that could probably just be outlawed. Since you would have to do the > equivalent of a scope resolution at every usage to tell the compiler what to do > (since *all* of the names would have collided), you might as well have just done > that and skipped the 'using' step. > > If you brought in different pieces of the same template, but from different > instantiations: > > using foo(int).Max; > using foo(double).Min; > > then there would be no namespace collision, and it might be allowable. Horribly > confusing, in the example given above, but possibly useful in some situations... > > Overall, I think that the 'using template foo(int);' form would be a handy addition for people who only needed a single instantiation of the template and > didn't want to have to precede every template member usage with 'intfoo.'. Trying to extend the usage beyond that, however, causes more problems than it > solves. > > Which leads me to my favorite solution so far, and it is even already in the > language (at least in the syntax, even if the template usage of it may not be in > the compiler yet) -- 'with'! > > with foo(int) > { > x = Max(a,b); > // more stuff, obviously > } > > or maybe: > > with inst foo(int) > { > } > > or: > > inst foo(int) intfoo; > with intfoo > { > } > > This saves adding another template specific keyword, explains how name collisions will be resolved (innermost 'with' clause that contains such a member > will win), and just generally seems nice and clean to me... That may be my > Visual Basic experience coming back to me (VB also uses 'with', and you use it a > LOT when you start getting OOPed in VB). > > Mac |
August 22, 2002 Re: template proposal | ||||
---|---|---|---|---|
| ||||
Posted in reply to Craig Black | It would also be real nice if version() statements inside the template could access the supplied actual template parameters. template Foo(T) { version(T.class.string == "int") { // do int thingy } else { // do generic thingy } } This can be simpler than specialization and is something I sorely miss in C++. Sean "Craig Black" <cblack@ara.com> wrote in message news:ak0h9n$1p37$1@digitaldaemon.com... > Hmmm .... this "namespace" approach to templates leans toward ease of implementation, which is good. > > Is there any way to do non-type template parameters? > > template VectorNamespace(T, int S) > { > class Vector > { > T[S] array; > } > } > > Also, I think that you should be able to do multiple specialization: > > template Foo(T) { ... } > template Foo(T : int, float, double) { ... } > > -Craig |
Copyright © 1999-2021 by the D Language Foundation