D - template proposal
- Walter (2/2) Aug 21 2002 www.digitalmars.com/template.html
-
Walter
(4/6)
Aug 21 2002
First thing I missed was the right url
- Russ Lewis (19/25) Aug 21 2002 max() and min() were presented to me as a classic problem that C++
- anderson (4/31) Aug 21 2002 That sounds more like a functional template then a class template. Parha...
- Walter (6/8) Aug 21 2002 D
- Juan Carlos Arevalo Baeza (6/9) Aug 21 2002 It's like a "template namespace", which is something I've always want...
- Walter (3/10) Aug 21 2002 Exactly!
- Walter (8/21) Aug 21 2002 You are correct that D does not do C++'s implicit instantiation, in D,
- Russell Lewis (3/27) Aug 21 2002 That was only part of the problem. I was also concerned about namespace...
- Walter (8/17) Aug 21 2002 that
- Russ Lewis (10/16) Aug 21 2002 In the "Argument Deduction" section, I don't understand the Bar(D, D :
- Walter (8/12) Aug 21 2002 That defines, to use C++ terminology, a "partial specialization", and is
- Russell Lewis (6/23) Aug 21 2002 What is the difference between
- Walter (4/18) Aug 21 2002 you
- Russell Lewis (2/27) Aug 21 2002 Oops, meant D[] on the latter one
- Walter (6/13) Aug 21 2002 In that case, it serves to distinguish:
- Russell Lewis (2/23) Aug 22 2002 And the difference between the two is?
- Pavel Minayev (4/13) Aug 22 2002
- Walter (3/11) Aug 23 2002 Yes, that's all it is. Think of it like function overloading.
- Russell Lewis (6/23) Aug 23 2002 Kind of like
- Pavel Minayev (3/5) Aug 23 2002 It was just an example! It doesn't have to be useful or even have sense....
- Walter (3/26) Aug 23 2002 Because Bar(int, int[]) is a specialization of Bar(T, U).
- Russell Lewis (8/42) Aug 26 2002 Ok, got you so far. So why declare it as
- Walter (5/13) Aug 26 2002 It could be:
- Russell Lewis (3/16) Aug 21 2002 Can you nest templates? Would it be useful to be able to derive one
- Walter (4/7) Aug 21 2002 Yes.
- anderson (12/14) Aug 21 2002 Looks pretty complete for my needs (although I'm no template expert). Si...
- Walter (6/16) Aug 21 2002 Simple
- Mac Reiter (46/46) Aug 21 2002 1. I would prefer something other than 'in' for 'instantiation'. I real...
- Russell Lewis (6/21) Aug 21 2002 As I understand it, the code would be
- Suporte Internet (4/9) Aug 21 2002 Why not use the keyword "typedef" ?
- Walter (6/9) Aug 21 2002 typedef is a good idea, the trouble comes from distinguishing a typedef ...
- Russell Lewis (3/16) Aug 21 2002 You could go the old C route:
- Walter (4/16) Aug 21 2002 from
- Martin M. Pedersen (9/10) Aug 21 2002 Hi,
- Walter (5/12) Aug 21 2002 It could, but instantiations of templates, as well as instantiations of
- Walter (57/99) Aug 21 2002 realize that
- Mac Reiter (8/16) Aug 21 2002 Thank you. I hadn't quite grokked that a template was a thing entirely ...
- Walter (13/20) Aug 21 2002 abc(int))
- Sandor Hojtsy (17/26) Aug 26 2002 to
- Walter (4/12) Aug 26 2002 Yes, it's a little more typing, but I think that it makes things a lot
- Jason Mills (3/61) Aug 21 2002 I agree. In addition, "in" is already used for "in" parameters and "in"
- Walter (22/48) Aug 21 2002 parameters are
- Mac Reiter (43/64) Aug 21 2002 [clip]
- Walter (31/63) Aug 21 2002 from
- Juan Carlos Arevalo Baeza (28/32) Aug 21 2002 not
- Walter (25/54) Aug 21 2002 were
- Juan Carlos Arevalo Baeza (27/42) Aug 22 2002 Hmmm... I guess...
- Pavel Minayev (4/6) Aug 22 2002 You can, as long as you pass those types as template parameters.
- Juan Carlos Arevalo Baeza (18/21) Aug 23 2002 user-defined
- Pavel Minayev (7/19) Aug 23 2002 I think you CAN do it. What Walter meant is that you can use MyClass dir...
- Juan Carlos Arevalo Baeza (25/41) Aug 23 2002 directly
- Walter (5/22) Aug 23 2002 addition
- Pavel Minayev (35/35) Aug 24 2002 On Fri=2C 23 Aug 2002 20=3A40=3A15 -0700 =22Walter=22 =3Cwalter=40digita...
- Walter (3/16) Aug 23 2002 Anything passed as a template argument *is* visible.
- Walter (10/24) Aug 23 2002 user-defined
- Sean L. Palmer (10/65) Aug 22 2002 This sounds like Pascal declaration syntax.
- Mac Reiter (27/44) Aug 22 2002 Actually taken from Eiffel, at least when I mentioned it. It does happe...
- Pavel Minayev (6/14) Aug 22 2002 "is
- Juan Carlos Arevalo Baeza (9/13) Aug 22 2002 this
- Russell Lewis (9/19) Aug 22 2002 I could see somebody wanting to do something like this:
- Walter (4/12) Aug 23 2002 I could see doing that with:
- Sandor Hojtsy (26/40) Aug 26 2002 Why would you need to pass on a completely dependent type as a seperate ...
- Walter (6/20) Aug 26 2002 type
- Craig Black (14/14) Aug 21 2002 Hmmm .... this "namespace" approach to templates leans toward ease of
- Walter (8/21) Aug 21 2002 It's a bit of an adjustment, but in the end I think it is superior.
- Mac Reiter (6/24) Aug 21 2002 It is entirely possible that my current QWERTY -> DVORAK immersion retra...
- Walter (7/12) Aug 21 2002 retraining is
- Sean L. Palmer (18/32) Aug 22 2002 It would also be real nice if version() statements inside the template c...
- Walter (5/20) Aug 23 2002 could
- Pavel Minayev (30/30) Aug 21 2002 On Wed=2C 21 Aug 2002 00=3A56=3A13 -0700 =22Walter=22 =3Cwalter=40digita...
- Walter (9/9) Aug 21 2002 I hear you, but I want to try it with explicit instantiation names first...
- Sean L. Palmer (6/15) Aug 22 2002 It's still explicit, it just isn't a declaration by itself, it's part of
- Walter (5/22) Aug 23 2002 I think that can work if it is prefaced by the keyword "instance".
- Pavel Minayev (4/4) Aug 24 2002 On Fri=2C 23 Aug 2002 20=3A40=3A53 -0700 =22Walter=22 =3Cwalter=40digita...
- Walter (6/7) Aug 24 2002 Yes.
- Walter (5/9) Aug 21 2002 I forgot to mention that has syntax parsing problems, too. How about thi...
- Joel Lucsy (10/26) Aug 21 2002 Just to throw it out:
- Pavel Minayev (2/7) Aug 21 2002 This is also fine!
- Mac Reiter (28/28) Aug 21 2002 One possible problem with the static but multiply nameable nature of tem...
- Walter (9/13) Aug 21 2002 The problem only occurs with template variables. It's really the same is...
- Patrick Down (28/33) Aug 21 2002 Templates. Cool!
- Walter (11/31) Aug 21 2002 Nope. The only thing it will pick up from the instantiation scope is the
- Patrick Down (27/37) Aug 22 2002 Have you see C++ template usage like this?
- Patrick Down (16/16) Aug 22 2002 What about this...
- Walter (3/19) Aug 22 2002 Offhand I don't see why that shouldn't work. -Walter
- Walter (3/27) Aug 22 2002 No, I haven't. But perhaps it can be done with interfaces.
- Patrick Down (5/7) Aug 22 2002 It's used extensivly by microsoft in ATL. It's one of those C++
- Martin M. Pedersen (13/15) Aug 21 2002 Hi,
- Martin M. Pedersen (8/9) Aug 21 2002 Hi,
- Walter (4/6) Aug 21 2002 member
- Martin M. Pedersen (32/33) Aug 21 2002 Hi,
- Juan Carlos Arevalo Baeza (13/14) Aug 21 2002 Butofcourse. Smart pointers and memory management don't necessarily h...
- Walter (6/9) Aug 21 2002 still
- Juan Carlos Arevalo Baeza (7/10) Aug 22 2002 Thanx.
- Sean L. Palmer (12/22) Aug 23 2002 I've been thinking along the same lines. I'd like to see what kind of
- Juan Carlos Arevalo Baeza (27/35) Aug 23 2002 language,
- Mac Reiter (89/103) Aug 22 2002 Minor semantic point, but the more general case of smart resource manage...
- Walter (5/5) Aug 22 2002 Your comments on smart handles in D explain it better than I have.
- Mac Reiter (9/14) Aug 22 2002 I know that 'counted' would increase the complexity of the compiler, whi...
- Walter (10/16) Aug 23 2002 you
- Mac Reiter (9/17) Aug 23 2002 Yup. Actually, I originally started thinking about a 'scoped' keyword w...
- Walter (9/15) Aug 23 2002 whose
- Pavel Minayev (6/13) Aug 22 2002 Note that if GC will still run on refcounted objects as well, it provide...
- Mac Reiter (10/23) Aug 22 2002 Thank you. I meant to illustrate reference counting as a means of minim...
- Walter (20/28) Aug 21 2002 I've thought about this. Wouldn't it make sense to have an argument that...
- Martin M. Pedersen (11/18) Aug 21 2002 Hi,
- anderson (12/14) Aug 22 2002 Wow, one day since this was posted and all these emails.
- Pavel Minayev (4/19) Aug 22 2002 Yes, just as if the function was overloaded (and any clashes like foo(in...
- anderson (13/32) Aug 27 2002 I though of another extention to that idea. How about if there is a
- Mac Reiter (49/66) Aug 22 2002 (The following message represents me thinking and typing at the same tim...
- Walter (20/68) Aug 22 2002 I hadn't thought of using the with, but it just might be the ticket. And...
- Pavel Minayev (19/19) Aug 22 2002 On Thu=2C 22 Aug 2002 14=3A46=3A31 +0000 =28UTC=29 Mac Reiter =3CMac=5Fm...
- anderson (18/95) Aug 28 2002 Sounds good
www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?
Aug 21 2002
"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?First thing I missed was the right url <sigh> www.digitalmars.com/d/template.html
Aug 21 2002
Walter wrote:"Walter" <walter digitalmars.com> wrote in message news:ajvgsb$6gt$1 digitaldaemon.com...max() and min() were presented to me as a classic problem that C++ templates were trying to solve. The beauty was that there only needed to be one declaration, and all types automatically got a max() function. It was a substitute for C's template solution. I don't see how D templates can do max and min, unless you explicitly instantiate them: in Max(int) maxint; val3 = maxint.max(val1,val2); That seems like an ugly solution to me, especially since (as I understand it), we can't use the same instantiation name for multiple different instantiations. If we're going to have to have a "maxint" template instantiation that's separate from a "maxfloat" and all the others, we might as well just define functions and save ourselves 4 characters of typing when we call it. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?First thing I missed was the right url <sigh> www.digitalmars.com/d/template.html
Aug 21 2002
That sounds more like a functional template then a class template. Parhaps D needs that as well? "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63793A.93407771 deming-os.org...Walter wrote:"Walter" <walter digitalmars.com> wrote in message news:ajvgsb$6gt$1 digitaldaemon.com...max() and min() were presented to me as a classic problem that C++ templates were trying to solve. The beauty was that there only needed to be one declaration, and all types automatically got a max() function. It was a substitute for C's template solution. I don't see how D templates can do max and min, unless you explicitly instantiate them: in Max(int) maxint; val3 = maxint.max(val1,val2); That seems like an ugly solution to me, especially since (as I understand it), we can't use the same instantiation name for multiple different instantiations. If we're going to have to have a "maxint" template instantiation that's separate from a "maxfloat" and all the others, we might as well just define functions and save ourselves 4 characters of typing when we call it. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?First thing I missed was the right url <sigh> www.digitalmars.com/d/template.html
Aug 21 2002
"anderson" <anderson firestar.com.au> wrote in message news:ak04p5$t3u$1 digitaldaemon.com...That sounds more like a functional template then a class template. ParhapsDneeds that as well?D does not have a distinction between class and function templates. An entire group of declarations of any kind can be within a template body, including classes, functions, variables, enums, nested templates, etc.
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in message news:ak0efd$1lp2$2 digitaldaemon.com...D does not have a distinction between class and function templates. An entire group of declarations of any kind can be within a template body, including classes, functions, variables, enums, nested templates, etc.It's like a "template namespace", which is something I've always wanted in C++. Salutaciones, JCAB
Aug 21 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak16eg$2q07$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:ak0efd$1lp2$2 digitaldaemon.com...Exactly!D does not have a distinction between class and function templates. An entire group of declarations of any kind can be within a template body, including classes, functions, variables, enums, nested templates, etc.It's like a "template namespace", which is something I've always wanted in C++.
Aug 21 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63793A.93407771 deming-os.org...max() and min() were presented to me as a classic problem that C++ templates were trying to solve. The beauty was that there only needed to be one declaration, and all types automatically got a max() function. It was a substitute for C's template solution. I don't see how D templates can do max and min, unless you explicitly instantiate them: in Max(int) maxint; val3 = maxint.max(val1,val2); That seems like an ugly solution to me, especially since (as I understand it), we can't use the same instantiation name for multiple different instantiations. If we're going to have to have a "maxint" template instantiation that's separate from a "maxfloat" and all the others, we might as well just define functions and save ourselves 4 characters of typing when we call it.You are correct that D does not do C++'s implicit instantiation, in D, instantiation must be explicit. The reason is I have come to believe that much of the complexity and problems with C++ templates comes from implicit instantiation - this is complexity in both specification and use. In practice, I find that many programs use typedef's to try and reduce the complexity and approximate explicit instantiation.
Aug 21 2002
Walter wrote:"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63793A.93407771 deming-os.org...That was only part of the problem. I was also concerned about namespace cluttering (maxint, maxfloat, etc. instead of just a single "max").max() and min() were presented to me as a classic problem that C++ templates were trying to solve. The beauty was that there only needed to be one declaration, and all types automatically got a max() function. It was a substitute for C's template solution. I don't see how D templates can do max and min, unless you explicitly instantiate them: in Max(int) maxint; val3 = maxint.max(val1,val2); That seems like an ugly solution to me, especially since (as I understand it), we can't use the same instantiation name for multiple different instantiations. If we're going to have to have a "maxint" template instantiation that's separate from a "maxfloat" and all the others, we might as well just define functions and save ourselves 4 characters of typing when we call it.You are correct that D does not do C++'s implicit instantiation, in D, instantiation must be explicit. The reason is I have come to believe that much of the complexity and problems with C++ templates comes from implicit instantiation - this is complexity in both specification and use. In practice, I find that many programs use typedef's to try and reduce the complexity and approximate explicit instantiation.
Aug 21 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63C9DD.3060203 deming-os.org...Walter wrote:thatYou are correct that D does not do C++'s implicit instantiation, in D, instantiation must be explicit. The reason is I have come to believeimplicitmuch of the complexity and problems with C++ templates comes fromThe advantage of that is you'll get much more reasonable error messages, rather than things like: Error: foo<<<t>bar<<>>>const T>>>***<<T,Q><int <<<>>> bar<q,int*><10> <g>instantiation - this is complexity in both specification and use. In practice, I find that many programs use typedef's to try and reduce the complexity and approximate explicit instantiation.That was only part of the problem. I was also concerned about namespace cluttering (maxint, maxfloat, etc. instead of just a single "max").
Aug 21 2002
Walter wrote:"Walter" <walter digitalmars.com> wrote in message news:ajvgsb$6gt$1 digitaldaemon.com...In the "Argument Deduction" section, I don't understand the Bar(D, D : D[]) example. Does this mean that you have only one template parameter, "D", and you have to specify it in 2 different ways? If not, then what does it mean? -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?First thing I missed was the right url <sigh> www.digitalmars.com/d/template.html
Aug 21 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D637991.FF91430E deming-os.org...In the "Argument Deduction" section, I don't understand the Bar(D, D : D[]) example. Does this mean that you have only one template parameter, "D", and you have to specify it in 2 different ways? If not, then what does it mean?That defines, to use C++ terminology, a "partial specialization", and is equivalent to the C++: template<class D> int Bar<D, D[]>() { } It means there are two arguments to the template, and to instantiate it you need to specify both. While this doesn't make a whole lot of sense by itself, it is to distinguish Bar(D,D[]) from another template Bar(D,E).
Aug 21 2002
Walter wrote:"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D637991.FF91430E deming-os.org...What is the difference between template Bar(D, D : D[]) {...} and template Bar(D : D{}) {...} ?In the "Argument Deduction" section, I don't understand the Bar(D, D : D[]) example. Does this mean that you have only one template parameter, "D", and you have to specify it in 2 different ways? If not, then what does it mean?That defines, to use C++ terminology, a "partial specialization", and is equivalent to the C++: template<class D> int Bar<D, D[]>() { } It means there are two arguments to the template, and to instantiate it you need to specify both. While this doesn't make a whole lot of sense by itself, it is to distinguish Bar(D,D[]) from another template Bar(D,E).
Aug 21 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63CB4E.30009 deming-os.org...Walter wrote:youThat defines, to use C++ terminology, a "partial specialization", and is equivalent to the C++: template<class D> int Bar<D, D[]>() { } It means there are two arguments to the template, and to instantiate itThe latter is illegal, as D{} is not a type.need to specify both. While this doesn't make a whole lot of sense by itself, it is to distinguish Bar(D,D[]) from another template Bar(D,E).What is the difference between template Bar(D, D : D[]) {...} and template Bar(D : D{}) {...} ?
Aug 21 2002
Walter wrote:"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63CB4E.30009 deming-os.org...Oops, meant D[] on the latter oneWalter wrote:youThat defines, to use C++ terminology, a "partial specialization", and is equivalent to the C++: template<class D> int Bar<D, D[]>() { } It means there are two arguments to the template, and to instantiate itThe latter is illegal, as D{} is not a type.need to specify both. While this doesn't make a whole lot of sense by itself, it is to distinguish Bar(D,D[]) from another template Bar(D,E).What is the difference between template Bar(D, D : D[]) {...} and template Bar(D : D{}) {...} ?
Aug 21 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63D965.4040809 deming-os.org...In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;Oops, meant D[] on the latter oneWhat is the difference between template Bar(D, D : D[]) {...} and template Bar(D : D{}) {...} ?The latter is illegal, as D{} is not a type.
Aug 21 2002
Walter wrote:"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63D965.4040809 deming-os.org...And the difference between the two is?In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;Oops, meant D[] on the latter oneWhat is the difference between template Bar(D, D : D[]) {...} and template Bar(D : D{}) {...} ?The latter is illegal, as D{} is not a type.
Aug 22 2002
On Thu, 22 Aug 2002 14:02:13 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:The first one gets one argument, the second gets two. =)In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;And the difference between the two is?
Aug 22 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374913480596065 news.digitalmars.com...On Thu, 22 Aug 2002 14:02:13 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:Yes, that's all it is. Think of it like function overloading.The first one gets one argument, the second gets two. =)In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;And the difference between the two is?
Aug 23 2002
Walter wrote:"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374913480596065 news.digitalmars.com...Kind of like void foo(int a,int b) in { assert(a == b); } {...} ??? If that's the case, why are we reusing the "Bar" name rather than just defining a new template name that only takes one argument???On Thu, 22 Aug 2002 14:02:13 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:Yes, that's all it is. Think of it like function overloading.The first one gets one argument, the second gets two. =)In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;And the difference between the two is?
Aug 23 2002
On Fri, 23 Aug 2002 11:21:40 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:If that's the case, why are we reusing the "Bar" name rather than just defining a new template name that only takes one argument???It was just an example! It doesn't have to be useful or even have sense. =)
Aug 23 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D667D34.3090803 deming-os.org...Walter wrote:Because Bar(int, int[]) is a specialization of Bar(T, U)."Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374913480596065 news.digitalmars.com...Kind of like void foo(int a,int b) in { assert(a == b); } {...} ??? If that's the case, why are we reusing the "Bar" name rather than just defining a new template name that only takes one argument???On Thu, 22 Aug 2002 14:02:13 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:Yes, that's all it is. Think of it like function overloading.The first one gets one argument, the second gets two. =)In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;And the difference between the two is?
Aug 23 2002
Walter wrote:"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D667D34.3090803 deming-os.org...Ok, got you so far. So why declare it as template Bar(D, D : D[]) {...} rather than template Bar(D, UNUSED_PARAM : D[]) {...} ??? The former looks like you're declaring the same parameter twice, with two different usages.Walter wrote:Because Bar(int, int[]) is a specialization of Bar(T, U)."Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374913480596065 news.digitalmars.com...Kind of like void foo(int a,int b) in { assert(a == b); } {...} ??? If that's the case, why are we reusing the "Bar" name rather than just defining a new template name that only takes one argument???On Thu, 22 Aug 2002 14:02:13 -0700 Russell Lewis <spamhole-2001-07-16 deming-os.org> wrote:Yes, that's all it is. Think of it like function overloading.The first one gets one argument, the second gets two. =)In that case, it serves to distinguish: instance Bar(int) x1; from: instance Bar(int, int[]) x2;And the difference between the two is?
Aug 26 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D6A69CC.5050106 deming-os.org...It could be: (D, :D[]) but I thought the : might appear invisible like that.Because Bar(int, int[]) is a specialization of Bar(T, U).Ok, got you so far. So why declare it as template Bar(D, D : D[]) {...} rather than template Bar(D, UNUSED_PARAM : D[]) {...} ??? The former looks like you're declaring the same parameter twice, with two different usages.
Aug 26 2002
Walter wrote:"Walter" <walter digitalmars.com> wrote in message news:ajvgsb$6gt$1 digitaldaemon.com...Can you nest templates? Would it be useful to be able to derive one template from another (to add memebers, not to override them)?www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?First thing I missed was the right url <sigh> www.digitalmars.com/d/template.html
Aug 21 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63DF06.6030202 deming-os.org...Can you nest templates?Yes.Would it be useful to be able to derive one template from another (to add memebers, not to override them)?Uh-oh! Maybe for V3 of the language!
Aug 21 2002
Looks pretty complete for my needs (although I'm no template expert). Simple yet powerful. Just a few questions. " template Foo(T); in Foo(int); // T is deduced to be int in Foo(char*); // T is deduced to be char* " I don't understand this where is the InstanceIdentifier? Or is this some type of overloaded function call? I guess this is a stupid question, but will it support operator overloading? "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?
Aug 21 2002
"anderson" <anderson firestar.com.au> wrote in message news:ajvr5q$i69$1 digitaldaemon.com...Looks pretty complete for my needs (although I'm no template expert).Simpleyet powerful. Just a few questions. " template Foo(T); in Foo(int); // T is deduced to be int in Foo(char*); // T is deduced to be char* " I don't understand this where is the InstanceIdentifier? Or is this some type of overloaded function call?I forgot to put in the InstanceIdentifier. Oops!I guess this is a stupid question, but will it support operatoroverloading? Sure.
Aug 21 2002
1. I would prefer something other than 'in' for 'instantiation'. I realize that 'instance' might be annoying to type, but I will never be able to look at 'in' and see anything except 'the opposite of out'. I could go with 'inst', which contains enough of the word to suggest 'instance' to me. (I have similar problems with the standard C++ STL notation of InIt for an Input Iterator -- it just looks like an initializer to me...) 2. How do I make two variables of type Foo(int)? According to the documentation, this appears to be explicitly disallowed -- "Multiple instantiations of a TemplateDeclaration with the same TemplateParameterList all will refer to the same instantiation." If I make a RedBlackTree(T), and then find myself needing two separate trees that both hold char[]s, how can I do that? I *could* typedef two different names for char[]s and make separate instances that way, but that just obscures the issue. Readers of the code then have to go look up my typedef to find out that it is just a char[] with no additional functionality. 3. It might be useful to have some way to say that some template parameters are "like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives from Bird inst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive from Bird inst Cage(Bird, Animal); // Error - inheritance order is backwards I'm not sure how useful this is in practice. I know Eiffel has a similar system, and Bertrand Meyer gets really excited about it, but I was never certain that I saw the benefit of this over using Base*s and letting vtables handle it. 4. I would really like constrained genericity. Similar to the above, but when you say a parameter is "like" some base class, the base class doesn't need to be another parameter to the template. template Calculator(T like NUMERIC) {/*whatever*/} In this case, NUMERIC is basically an interface. The standard argument against this is that if someone tries to instantiate the template with a class that is not NUMERIC, something will fail when Calculator tries to use one of the NUMERIC members. But it is possible (even if unlikely) that a non-NUMERIC class could accidentally implement enough of NUMERIC to let it work, but not work the way Calculator expects. Calculator is a bad example of this, since anyone providing NUMERIC-style members probably is doing numerical work -- but for other templates and other interfaces, the issue is not as clear. The other benefit is self-documentation. By placing it in the code, the developer makes it clear what he/she is requiring for the template parameter. It becomes part of the contract. I have no particular attachment to the word "like" in either of the above points. It just happened to be the first thing I thought of. "implements" might not be a bad choice, although it is rather wordy ( T implements NUMERIC ). "isa" or "is_a" might work too ( T isa NUMERIC ). Mac
Aug 21 2002
Mac Reiter wrote:1. I would prefer something other than 'in' for 'instantiation'. I realize that 'instance' might be annoying to type, but I will never be able to look at 'in' and see anything except 'the opposite of out'. I could go with 'inst', which contains enough of the word to suggest 'instance' to me. (I have similar problems with the standard C++ STL notation of InIt for an Input Iterator -- it just looks like an initializer to me...)Hear, Hear2. How do I make two variables of type Foo(int)? According to the documentation, this appears to be explicitly disallowed -- "Multiple instantiations of a TemplateDeclaration with the same TemplateParameterList all will refer to the same instantiation." If I make a RedBlackTree(T), and then find myself needing two separate trees that both hold char[]s, how can I do that? I *could* typedef two different names for char[]s and make separate instances that way, but that just obscures the issue. Readers of the code then have to go look up my typedef to find out that it is just a char[] with no additional functionality.As I understand it, the code would be in RedBlackTree(char[]) RedBlackTree_of_char_array; RedBlackTree_of_char_array var1; RedBlackTree_of_char_array var2;
Aug 21 2002
Mac Reiter <Mac_member pathlink.com> wrote:1. I would prefer something other than 'in' for 'instantiation'. I realize that 'instance' might be annoying to type, but I will never be able to look at 'in' and see anything except 'the opposite of out'. I could go with 'inst', which contains enough of the word to suggest 'instance' to me. (I have similar problems with the standard C++ STL notation of InIt for an Input Iterator -- itWhy not use the keyword "typedef" ? This is not what is doing ? You are creating a new type based on a template ?
Aug 21 2002
"Suporte Internet" <suporte spica.mps.com.br> wrote in message news:ak0dea$1ich$1 digitaldaemon.com...Why not use the keyword "typedef" ? This is not what is doing ? You are creating a new type based on a template ?typedef is a good idea, the trouble comes from distinguishing a typedef from a declaration just by the syntax: typedef foo(int*) f;
Aug 21 2002
Walter wrote:"Suporte Internet" <suporte spica.mps.com.br> wrote in message news:ak0dea$1ich$1 digitaldaemon.com...You could go the old C route: typedef template foo(int*) f;Why not use the keyword "typedef" ? This is not what is doing ? You are creating a new type based on a template ?typedef is a good idea, the trouble comes from distinguishing a typedef from a declaration just by the syntax: typedef foo(int*) f;
Aug 21 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D63CB8E.3030608 deming-os.org...Walter wrote:from"Suporte Internet" <suporte spica.mps.com.br> wrote in message news:ak0dea$1ich$1 digitaldaemon.com...Why not use the keyword "typedef" ? This is not what is doing ? You are creating a new type based on a template ?typedef is a good idea, the trouble comes from distinguishing a typedefI think I'd rather use the keyword 'instance' <g>.a declaration just by the syntax: typedef foo(int*) f;You could go the old C route: typedef template foo(int*) f;
Aug 21 2002
Hi, "Walter" <walter digitalmars.com> wrote in message news:ak0j61$1r42$2 digitaldaemon.com...I think I'd rather use the keyword 'instance' <g>.Couldn't it cause some confusion with instances of classes, which are objects? Instances of a template is an interely different thing. How about "concrete", meaning that you make the abstract template concrete by supplying types. Regards, Martin M. Pedersen
Aug 21 2002
"Martin M. Pedersen" <mmp www.moeller-pedersen.dk> wrote in message news:ak0sto$ic1$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:ak0j61$1r42$2 digitaldaemon.com...It could, but instantiations of templates, as well as instantiations of classes, are both commonly referred to as instances. Your point is likely why Ada instantiates templates with the 'new' keyword.I think I'd rather use the keyword 'instance' <g>.Couldn't it cause some confusion with instances of classes, which are objects? Instances of a template is an interely different thing. How about "concrete", meaning that you make the abstract template concrete by supplying types.
Aug 21 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak09pv$1b4k$1 digitaldaemon.com...1. I would prefer something other than 'in' for 'instantiation'. Irealize that'instance' might be annoying to type, but I will never be able to look at'in'and see anything except 'the opposite of out'. I could go with 'inst',whichcontains enough of the word to suggest 'instance' to me. (I have similar problems with the standard C++ STL notation of InIt for an InputIterator -- itjust looks like an initializer to me...)I was afraid that 'instance' just was too long. An alternative is to use 'new' sort of like Ada. But you might be right.2. How do I make two variables of type Foo(int)?You don't - Foo is a template, not a type. A type could be declared inside the template: template Foo(T) { typedef T abc; } instance Foo(int) myfoo; // Declare multiple variables: myfoo.abc var1; myfoo.abc var2;According to the documentation, this appears to be explicitly disallowed -- "Multiple instantiations of a TemplateDeclaration with the sameTemplateParameterList allwill refer to the same instantiation." If I make a RedBlackTree(T), andthenfind myself needing two separate trees that both hold char[]s, how can Idothat? I *could* typedef two different names for char[]s and make separate instances that way, but that just obscures the issue. Readers of the codethenhave to go look up my typedef to find out that it is just a char[] with no additional functionality.In that case, it sounds like one should write: template RedBlackTree(T) { class Foo { char[] s; } } instance RedBlackTree(whatever) mytree; // Now create multiple independent trees, each with their own data: mytree.Foo f = new mytree(Foo); mytree.Foo g = new mytree(Foo);3. It might be useful to have some way to say that some templateparameters are"like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives from Bird inst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive from Bird inst Cage(Bird, Animal); // Error - inheritance order is backwards I'm not sure how useful this is in practice. I know Eiffel has a similar system, and Bertrand Meyer gets really excited about it, but I was nevercertainthat I saw the benefit of this over using Base*s and letting vtableshandle it. That could possibly be handled by a contract: template Cage(Base, Derived) { class Foo { Base b; Derived d; invariant { assert(cast(Base)d != null); } } }4. I would really like constrained genericity. Similar to the above, butwhenyou say a parameter is "like" some base class, the base class doesn't needto beanother parameter to the template. template Calculator(T like NUMERIC) {/*whatever*/} In this case, NUMERIC is basically an interface. The standard argumentagainstthis is that if someone tries to instantiate the template with a classthat isnot NUMERIC, something will fail when Calculator tries to use one of theNUMERICmembers. But it is possible (even if unlikely) that a non-NUMERIC classcouldaccidentally implement enough of NUMERIC to let it work, but not work thewayCalculator expects. Calculator is a bad example of this, since anyoneprovidingNUMERIC-style members probably is doing numerical work -- but for other templates and other interfaces, the issue is not as clear. The otherbenefit isself-documentation. By placing it in the code, the developer makes itclearwhat he/she is requiring for the template parameter. It becomes part ofthecontract.That is a good suggestion. Note that there are already ways to constrain it to be, say, an array type: template Foo(T : T[])
Aug 21 2002
Thank you. I hadn't quite grokked that a template was a thing entirely to itself. The extra level of indirection (myfoo.abc rather than just abc(int)) had not really clicked. Now that I see that, the RedBlack(char) question goes away. I really like being able to make an arbitrary amount of stuff inside a template, all based on the same instantiation parameters. I'll have to think about it some more before I can give any useful feedback... Mac2. How do I make two variables of type Foo(int)?You don't - Foo is a template, not a type. A type could be declared inside the template: template Foo(T) { typedef T abc; } instance Foo(int) myfoo; // Declare multiple variables: myfoo.abc var1; myfoo.abc var2;
Aug 21 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak0ltg$2hjd$1 digitaldaemon.com...Thank you. I hadn't quite grokked that a template was a thing entirely to itself. The extra level of indirection (myfoo.abc rather than justabc(int))had not really clicked. Now that I see that, the RedBlack(char) questiongoesaway.Yup. It's perilous to break from the C++ mindset on how it should work <g>.I really like being able to make an arbitrary amount of stuff inside atemplate,all based on the same instantiation parameters. I'll have to think aboutitsome more before I can give any useful feedback...It has the nice feature of simply chucking the whole C++ messy distinctions between template classes, template functions, member template functions (or is it template member functions?), etc. In many more complex cases of this, it can get really tricky for the C++ compiler to parse which is which. In D, the template syntax is a no-brainer to implement. (Semantic analysis is a little harder!)
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in message news:ak0rom$app$2 digitaldaemon.com..."Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak0ltg$2hjd$1 digitaldaemon.com...toThank you. I hadn't quite grokked that a template was a thing entirelyquestionitself. The extra level of indirection (myfoo.abc rather than justabc(int))had not really clicked. Now that I see that, the RedBlack(char)goes<g>. But do we want that extra indirection, after all? In practice you usually need class templates. You will end up typedef-ing everything, to avoid the burden of the unnecessary indirection. typedef RedBlackTree instance RBT_Template(char).TheClassInside; Makes me feel like Java, with all the superfluous indirections. And class templates also allow for function templates as static member functions. Sorry if this was already metioned. I don't have the time to read all the hundreds of mails in this thread. Yours, Sandoraway.Yup. It's perilous to break from the C++ mindset on how it should work
Aug 26 2002
"Sandor Hojtsy" <hojtsy index.hu> wrote in message news:akd51e$1hvo$1 digitaldaemon.com...But do we want that extra indirection, after all? In practice you usually need class templates. You will end up typedef-ing everything, to avoid the burden of the unnecessary indirection. typedef RedBlackTree instance RBT_Template(char).TheClassInside; Makes me feel like Java, with all the superfluous indirections. And class templates also allow for function templates as static member functions.Yes, it's a little more typing, but I think that it makes things a lot clearer.
Aug 26 2002
Mac Reiter wrote:1. I would prefer something other than 'in' for 'instantiation'. I realize that 'instance' might be annoying to type, but I will never be able to look at 'in' and see anything except 'the opposite of out'. I could go with 'inst', which contains enough of the word to suggest 'instance' to me. (I have similar problems with the standard C++ STL notation of InIt for an Input Iterator -- it just looks like an initializer to me...)I agree. In addition, "in" is already used for "in" parameters and "in" contracts.2. How do I make two variables of type Foo(int)? According to the documentation, this appears to be explicitly disallowed -- "Multiple instantiations of a TemplateDeclaration with the same TemplateParameterList all will refer to the same instantiation." If I make a RedBlackTree(T), and then find myself needing two separate trees that both hold char[]s, how can I do that? I *could* typedef two different names for char[]s and make separate instances that way, but that just obscures the issue. Readers of the code then have to go look up my typedef to find out that it is just a char[] with no additional functionality. 3. It might be useful to have some way to say that some template parameters are "like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives from Bird inst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive from Bird inst Cage(Bird, Animal); // Error - inheritance order is backwards I'm not sure how useful this is in practice. I know Eiffel has a similar system, and Bertrand Meyer gets really excited about it, but I was never certain that I saw the benefit of this over using Base*s and letting vtables handle it. 4. I would really like constrained genericity. Similar to the above, but when you say a parameter is "like" some base class, the base class doesn't need to be another parameter to the template. template Calculator(T like NUMERIC) {/*whatever*/} In this case, NUMERIC is basically an interface. The standard argument against this is that if someone tries to instantiate the template with a class that is not NUMERIC, something will fail when Calculator tries to use one of the NUMERIC members. But it is possible (even if unlikely) that a non-NUMERIC class could accidentally implement enough of NUMERIC to let it work, but not work the way Calculator expects. Calculator is a bad example of this, since anyone providing NUMERIC-style members probably is doing numerical work -- but for other templates and other interfaces, the issue is not as clear. The other benefit is self-documentation. By placing it in the code, the developer makes it clear what he/she is requiring for the template parameter. It becomes part of the contract. I have no particular attachment to the word "like" in either of the above points. It just happened to be the first thing I thought of. "implements" might not be a bad choice, although it is rather wordy ( T implements NUMERIC ). "isa" or "is_a" might work too ( T isa NUMERIC ). Mac
Aug 21 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak09pv$1b4k$1 digitaldaemon.com...3. It might be useful to have some way to say that some templateparameters are"like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives from Bird inst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive from Bird inst Cage(Bird, Animal); // Error - inheritance order is backwards I'm not sure how useful this is in practice. I know Eiffel has a similar system, and Bertrand Meyer gets really excited about it, but I was nevercertainthat I saw the benefit of this over using Base*s and letting vtableshandle it.4. I would really like constrained genericity. Similar to the above, butwhenyou say a parameter is "like" some base class, the base class doesn't needto beanother parameter to the template. template Calculator(T like NUMERIC) {/*whatever*/} In this case, NUMERIC is basically an interface. The standard argumentagainstthis is that if someone tries to instantiate the template with a classthat isnot NUMERIC, something will fail when Calculator tries to use one of theNUMERICmembers. But it is possible (even if unlikely) that a non-NUMERIC classcouldaccidentally implement enough of NUMERIC to let it work, but not work thewayCalculator expects. Calculator is a bad example of this, since anyoneprovidingNUMERIC-style members probably is doing numerical work -- but for other templates and other interfaces, the issue is not as clear. The otherbenefit isself-documentation. By placing it in the code, the developer makes itclearwhat he/she is requiring for the template parameter. It becomes part ofthecontract.It occurs to me that this does fit in with the D template syntax: template Calculator(T : NUMERIC) { ... } means that T can be either NUMERIC or a class derived from NUMERIC (if NUMERIC is a class or interface). Your case 3 would be: template Cage(B, D : B) {/*whatever*/} which would constrain D to be the same as B or derived from B.
Aug 21 2002
In article <ak0rom$app$3 digitaldaemon.com>, Walter says..."Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak09pv$1b4k$1 digitaldaemon.com...[clip]3. It might be useful to have some way to say that some templateparameters are"like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives from Bird inst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive from Bird inst Cage(Bird, Animal); // Error - inheritance order is backwards[clip]template Calculator(T like NUMERIC) {/*whatever*/}It occurs to me that this does fit in with the D template syntax: template Calculator(T : NUMERIC) { ... } means that T can be either NUMERIC or a class derived from NUMERIC (if NUMERIC is a class or interface). Your case 3 would be: template Cage(B, D : B) {/*whatever*/} which would constrain D to be the same as B or derived from B.Even better. The 'T : NUMERIC' syntax is much like the Eiffel syntax I was coming from. I didn't know if it would work that way in D or not. The examples with : were demonstrating partial template specialization (or the D equivalent) and the ability to pull types out of pointers to / arrays of types. I didn't know if the constraint system supported general purpose "is a" constraints, including direct and indirect inheritance. There appears to be some semantic difference: template Calc(T : NUMERIC) template Other(T : T[]) In the first case, I would instantiate Calc with a class that was derived from NUMERIC (or NUMERIC itself, if NUMERIC is concrete). But in the second case, I instantiate Calc with an array, and the compiler extracts the type. If these two cases behaved identically, then either: 1. Take the first example as the standard -- Other must now be instantiated with a single variable, and the type of that variable is required to support the interface of an array of that type. T is required to act as if it is an array of T, which it can't do. 2. Take the second example as the standard -- Calc must now be instantiated with a NUMERIC, and the D compiler will deduce an appropriate type for T. I suppose this would be possible with RTTI, or by allowing the compiler to take derivatives of NUMERIC directly... I guess my mental hangup is that 'T:NUMERIC' means "T must support the NUMERIC interface" (derive from it, whatever), but 'T:T[]' means "given a T[], extract T". Having had Eiffel training in constrained genericity, I tend to favor the "must support" semantics, but I am trying to maintain an open mind... I know that you've been thinking about this for quite some time, and I also know that it is difficult to come up with small simple examples that illustrate the intended usage of some of these features. (My examples when trying to show this stuff to my coworkers is almost always horrible) The 'template X(T,T:T[])' examples so far seem like they shouldn't need the second parameter, since if you know T you can always make a T[] inside the template. In C++ you need this sort of thing in case the user is using smart array classes, smart pointer classes, iterators, etc. But in D, arrays are arrays, pointers are pointers, etc, so there doesn't seem to be the need to allow the user to specify *how* to make an array out of the base type. Could you give us an example (even if it is somewhat complicated) of the case you were considering when you made the 'template X(T,T:T[])' behavior? I'm sure there's a reason that I'm just overlooking. Thanks, Mac
Aug 21 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak0tm6$njk$1 digitaldaemon.com...There appears to be some semantic difference: template Calc(T : NUMERIC) template Other(T : T[]) In the first case, I would instantiate Calc with a class that was derivedfromNUMERIC (or NUMERIC itself, if NUMERIC is concrete). But in the secondcase, Iinstantiate Calc with an array, and the compiler extracts the type. Ifthesetwo cases behaved identically, then either: 1. Take the first example as the standard -- Other must now beinstantiated witha single variable, and the type of that variable is required to supporttheinterface of an array of that type. T is required to act as if it is anarrayof T, which it can't do. 2. Take the second example as the standard -- Calc must now beinstantiated witha NUMERIC, and the D compiler will deduce an appropriate type for T. Isupposethis would be possible with RTTI, or by allowing the compiler to take derivatives of NUMERIC directly... I guess my mental hangup is that 'T:NUMERIC' means "T must support theNUMERICinterface" (derive from it, whatever), but 'T:T[]' means "given a T[],extractT". Having had Eiffel training in constrained genericity, I tend to favorthe"must support" semantics, but I am trying to maintain an open mind...You're right, there is a subtle difference there. I think if the rule were if T is in the specialization, then the value of T is extracted. If T is not in the specialization, T is whatever the whole specialization type is (or derived from it).I know that you've been thinking about this for quite some time, and Ialso knowthat it is difficult to come up with small simple examples that illustratetheintended usage of some of these features. (My examples when trying toshow thisstuff to my coworkers is almost always horrible) The 'templateX(T,T:T[])'examples so far seem like they shouldn't need the second parameter, sinceif youknow T you can always make a T[] inside the template. In C++ you needthis sortof thing in case the user is using smart array classes, smart pointerclasses,iterators, etc. But in D, arrays are arrays, pointers are pointers, etc,sothere doesn't seem to be the need to allow the user to specify *how* tomake anarray out of the base type. Could you give us an example (even if it is somewhat complicated) of the case you were considering when you made the 'template X(T,T:T[])' behavior? I'm sure there's a reason that I'm just overlooking.I don't have a good example. One thing about C++, there seems to be a veritable army of very smart people discovering clever things to do with C++ templates that weren't anticipated in the initial design of templates. The X(T,T:T[]) falls out of the specialization syntax, so there's no obvious reason to disallow it.
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in message news:ak11s6$1lac$1 digitaldaemon.com...You're right, there is a subtle difference there. I think if the rule were if T is in the specialization, then the value of T is extracted. If T isnotin the specialization, T is whatever the whole specialization type is (or derived from it).Or you can use a different operator to make it even simpler to parse. => and := come to mind... Still, using runtime interfaces for this sounds a little wrong to me. One thing that I don't like is not having numeric/value template parameters. And, now that we're at it, "TemplateInstantiations are always performed in the scope of where the TemplateDeclaration is declared, with the addition of the template parameters being declared as aliases for their deduced types", so what's the semantics of this: --- void func(int) { ... } template Tpl(T) { void anotherfunc(T t) { func(t); } } void func(bool) { ... } instance Tpl(bool) tplBool; // How? tplBool.anotherfunc(false); // How? --- I guess that with the non-need for function prototypes, this particular example is solvable in D. But I'm thinking especially of templates defined in one module and used in another. Salutaciones, JCAB
Aug 21 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak1fat$2c87$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:ak11s6$1lac$1 digitaldaemon.com...wereYou're right, there is a subtle difference there. I think if the rule(orif T is in the specialization, then the value of T is extracted. If T isnotin the specialization, T is whatever the whole specialization type is=>derived from it).Or you can use a different operator to make it even simpler to parse.and := come to mind... Still, using runtime interfaces for this sounds a little wrong to me.It's still compile time, just a bit extra work for the semantic pass. Not too tough, C++ templates are far worse <g>. I just have to adapt the argument type deduction code from that, meanwhile whacking off about 90% of it.One thing that I don't like is not having numeric/value template parameters.Just use them as class members, and pass the class type.And, now that we're at it, "TemplateInstantiations are always performed in the scope of where the TemplateDeclaration is declared, with theadditionof the template parameters being declared as aliases for their deduced types", so what's the semantics of this: --- void func(int) { ... } template Tpl(T) { void anotherfunc(T t) { func(t); } } void func(bool) { ... } instance Tpl(bool) tplBool; // How? tplBool.anotherfunc(false); // How?It doesn't matter if some functions are before and some after the use of it, the compiler sees all of them when doing the semantic analysis. This just doesn't have the problems/bugs inherent in the C++ model of not knowing about anything ahead of it in the source file. Hence, the call func(t) will resolve to func(bool), regardless of the lexical positioning of func(int) and func(bool).I guess that with the non-need for function prototypes, this particular example is solvable in D. But I'm thinking especially of templates defined in one module and used in another.If func() is defined in a different module than template Tpl() and is not visible in the scope of template Tpl(), then you'll get a "func undefined" message when the instance Tpl(bool) is compiled regardless of whether func() is visible at the scope of instance Tpl(bool) or not. This is fundamentally different than the way C++ works - C++ tries to do it both ways, with some names getting resolved at template declaration scope, and some at template instantiation scope, depending on whether a name is "type-dependent" or not.
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in message news:ak1k42$j5f$1 digitaldaemon.com...Hmmm... I guess...Still, using runtime interfaces for this sounds a little wrong to me.It's still compile time, just a bit extra work for the semantic pass.It doesn't matter if some functions are before and some after the use ofit,the compiler sees all of them when doing the semantic analysis.Ok... I figured that.particularI guess that with the non-need for function prototypes, thisdefinedexample is solvable in D. But I'm thinking especially of templatesfunc()in one module and used in another.If func() is defined in a different module than template Tpl() and is not visible in the scope of template Tpl(), then you'll get a "func undefined" message when the instance Tpl(bool) is compiled regardless of whetheris visible at the scope of instance Tpl(bool) or not.So you can't really use templates taken from a library with user-defined types unless those user defined types are already known to the library?This is fundamentally different than the way C++ works - C++ tries to doitboth ways, with some names getting resolved at template declaration scope, and some at template instantiation scope, depending on whether a name is "type-dependent" or not.Yes, and we agree that's bad. Still, unless you have a clever answer to this, I can't see how your solution is good enough. I know you don't like forward declarations, but they might be warranted in the case of templates: template Tpl(T) { exists void func(T); // forward declaration... void anotherfunc(T t) { func(t); } } This would allow you to eliminate all problems with dependent names. It'll also allow the compiler to do even better error messages for invalid instantiations. In a way, you can consider this as compile-time contracts for templates. Salutaciones, JCAB
Aug 22 2002
On Thu, 22 Aug 2002 12:58:44 -0700 "Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote:So you can't really use templates taken from a library with user-defined types unless those user defined types are already known to the library?You can, as long as you pass those types as template parameters.
Aug 22 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374913474843634 news.digitalmars.com...user-definedSo you can't really use templates taken from a library withBut not unless those types were visible at the point where the template was declared. So: --- mylibrary.d template Tpl(T) { ... } --- --- myprogram.d using mylibrary; class MyClass { ... } instance Tpl(MyClass) TplMyClass; // Fails!!! --- That's what Walter seems to be saying. That the instantiation fails because MyClass is not visible in mylibrary.d. And that's what I have a problem with. Salutaciones, JCABtypes unless those user defined types are already known to the library?You can, as long as you pass those types as template parameters.
Aug 23 2002
On Fri, 23 Aug 2002 10:50:45 -0700 "Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote:"Pavel Minayev" <evilone omen.ru> wrote in message --- mylibrary.d template Tpl(T) { ... } --- --- myprogram.d using mylibrary; class MyClass { ... } instance Tpl(MyClass) TplMyClass; // Fails!!! ---I think you CAN do it. What Walter meant is that you can use MyClass directly from Tpl if it is declared in the same module with Tpl. Otherwise, you have to pass it as a template argument.
Aug 23 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374919430425 news.digitalmars.com...directly--- mylibrary.d template Tpl(T) { ... } --- --- myprogram.d using mylibrary; class MyClass { ... } instance Tpl(MyClass) TplMyClass; // Fails!!! ---I think you CAN do it. What Walter meant is that you can use MyClassfrom Tpl if it is declared in the same module with Tpl. Otherwise, you have topassit as a template argument.Well, that's not what I was asking to Walter. "TemplateInstantiations are always performed in the scope of where the TemplateDeclaration is declared, with the addition of the template parameters being declared as aliases for their deduced types" Let's update my second example: --- mylibrary.d template Tpl(T) { void tplfunc(T t) { func(t); } } --- --- myprogram.d using mylibrary; class MyClass { ... } void func(MyClass) { ... } instance Tpl(MyClass) TplMyClass; // Fails!!! --- Salutaciones, JCAB
Aug 23 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak687r$2h6e$1 digitaldaemon.com..."TemplateInstantiations are always performed in the scope of where the TemplateDeclaration is declared, with theadditionof the template parameters being declared as aliases for their deduced types" Let's update my second example: --- mylibrary.d template Tpl(T) { void tplfunc(T t) { func(t); } } --- --- myprogram.d using mylibrary; class MyClass { ... } void func(MyClass) { ... } instance Tpl(MyClass) TplMyClass; // Fails!!!Yes, that will fail. To make it work, func(MyClass) would need to be a class member of some class passed as a template argument.
Aug 23 2002
On Fri=2C 23 Aug 2002 20=3A40=3A15 -0700 =22Walter=22 =3Cwalter=40digitalmars=2Ecom=3E wrote=3A =3E=3E Let's update my second example=3A =3E=3E =3E=3E --- mylibrary=2Ed =3E=3E template Tpl=28T=29 { =3E=3E void tplfunc=28T t=29 { =3E=3E func=28t=29=3B =3E=3E } =3E=3E } =3E=3E --- =3E=3E =3E=3E --- myprogram=2Ed =3E=3E using mylibrary=3B =3E=3E =3E=3E class MyClass { =2E=2E=2E } =3E=3E =3E=3E void func=28MyClass=29 { =2E=2E=2E } =3E=3E =3E=3E instance Tpl=28MyClass=29 TplMyClass=3B =2F=2F Fails!!! =3E =3E Yes=2C that will fail=2E To make it work=2C func=28MyClass=29 would need to be a class =3E member of some class passed as a template argument=2E To fix it=3A =09template Tpl=28T=2C Func=29 =09{ =09=09void tplfunc=28T t=29 { Func=2Ecall=28t=29=3B } =09} =09class MyClass { =2E=2E=2E } =09void func=28MyClass=29 { =2E=2E=2E } =09class Func=5FMyClass =09{ =09=09static void call=28MyClass x=29 { func x=3B } =09} =09instance Tpl=28MyClass=2C Func=5FMyClass=29 TplMyClass=3B =2F=2F Works!
Aug 24 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak5s95$24i6$1 digitaldaemon.com...But not unless those types were visible at the point where the template was declared. So: --- mylibrary.d template Tpl(T) { ... } --- --- myprogram.d using mylibrary; class MyClass { ... } instance Tpl(MyClass) TplMyClass; // Fails!!! --- That's what Walter seems to be saying. That the instantiation fails because MyClass is not visible in mylibrary.d. And that's what I have a problem with.Anything passed as a template argument *is* visible.
Aug 23 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak3fd7$2dhu$1 digitaldaemon.com...So you can't really use templates taken from a library withuser-definedtypes unless those user defined types are already known to the library?Yes you can, if you pass the user defined type as a template argument.I know you don't like forward declarations, but they might be warranted in the case of templates: template Tpl(T) { exists void func(T); // forward declaration... void anotherfunc(T t) { func(t); } } This would allow you to eliminate all problems with dependent names. It'll also allow the compiler to do even better error messages for invalid instantiations. In a way, you can consider this as compile-time contracts for templates.You can do things like: template Tpl(T) { T.func(t); } Won't that fit the bill?
Aug 23 2002
This sounds like Pascal declaration syntax. Sean "Walter" <walter digitalmars.com> wrote in message news:ak0rom$app$3 digitaldaemon.com..."Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak09pv$1b4k$1 digitaldaemon.com...Bird3. It might be useful to have some way to say that some templateparameters are"like" or "derived from" other template parameters: template Cage(Base, Derived like Base) {/*whatever*/} Then at instantiation: inst Cage(Bird, Cockateel); // OK, assuming Cockateel derives fromBirdinst Cage(Bird, Bird); // OK inst Cage(Bird, Collie); // Error - Collie does not derive fromsimilarinst Cage(Bird, Animal); // Error - inheritance order is backwards I'm not sure how useful this is in practice. I know Eiffel has abutsystem, and Bertrand Meyer gets really excited about it, but I was nevercertainthat I saw the benefit of this over using Base*s and letting vtableshandle it.4. I would really like constrained genericity. Similar to the above,whenneedyou say a parameter is "like" some base class, the base class doesn'tto betheanother parameter to the template. template Calculator(T like NUMERIC) {/*whatever*/} In this case, NUMERIC is basically an interface. The standard argumentagainstthis is that if someone tries to instantiate the template with a classthat isnot NUMERIC, something will fail when Calculator tries to use one of theNUMERICmembers. But it is possible (even if unlikely) that a non-NUMERIC classcouldaccidentally implement enough of NUMERIC to let it work, but not workwayCalculator expects. Calculator is a bad example of this, since anyoneprovidingNUMERIC-style members probably is doing numerical work -- but for other templates and other interfaces, the issue is not as clear. The otherbenefit isself-documentation. By placing it in the code, the developer makes itclearwhat he/she is requiring for the template parameter. It becomes part ofthecontract.It occurs to me that this does fit in with the D template syntax: template Calculator(T : NUMERIC) { ... } means that T can be either NUMERIC or a class derived from NUMERIC (if NUMERIC is a class or interface). Your case 3 would be: template Cage(B, D : B) {/*whatever*/} which would constrain D to be the same as B or derived from B.
Aug 22 2002
In article <ak36u4$23sj$1 digitaldaemon.com>, Sean L. Palmer says...This sounds like Pascal declaration syntax. SeanActually taken from Eiffel, at least when I mentioned it. It does happen to be the same syntax as Pascal's: var I : INTEGER; I suppose that for UML people, some simulation of the inheritance arrow might be better: template Calc(T=>NUMERIC) or template Calc(T->NUMERIC) I don't know if this causes lexing/parsing problems or not. It is about as close as I can think of to UML's method of showing that T inherits from NUMERIC. I personally don't have a problem with the ':' syntax and its simularity to Pascal. I suppose it might cause problems for Delphi programmers, but anyone used to any older form of Pascal is going to be going through so many mental contortions anyway that they probably wouldn't even notice it. Even if they did, it is still vaguely appropriate: I : INTEGER; means that I "is an" INTEGER. T : NUMERIC means that T "is a" NUMERIC. It just happens to be the case that in OOP the "is a" relationship is much more flexible than it was in Pascal... I'm cool with almost any form, as long as it provides compile time type constraints for the template parameters. Mac (the following is for reference...)"Walter" <walter digitalmars.com> wrote in message news:ak0rom$app$3 digitaldaemon.com...[clip]"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak09pv$1b4k$1 digitaldaemon.com...It occurs to me that this does fit in with the D template syntax: template Calculator(T : NUMERIC) { ... } means that T can be either NUMERIC or a class derived from NUMERIC (if NUMERIC is a class or interface). Your case 3 would be: template Cage(B, D : B) {/*whatever*/} which would constrain D to be the same as B or derived from B.
Aug 22 2002
On Thu, 22 Aug 2002 18:25:46 +0000 (UTC) Mac Reiter <Mac_member pathlink.com> wrote:I : INTEGER; means that I "is an" INTEGER. T : NUMERIC means that T "is a" NUMERIC. It just happens to be the case that in OOP the"isa" relationship is much more flexible than it was in Pascal...Yes, exactly. Being a hardcore Pascal fan once, I must admit that I like this syntax partially because it reminds me of good old TP days... =)
Aug 22 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374909701815972 news.digitalmars.com...thisT : NUMERICYes, exactly. Being a hardcore Pascal fan once, I must admit that I likesyntax partially because it reminds me of good old TP days... =)He he... I've come to like it better than the C/C++ syntax. Much clearer, much less ambiguous, and it rationalizes the use of type expressions, by making them look exactly the same wether you're casting, or specifying a template argument, or declaring a variable of such type. Salutaciones, JCAB
Aug 22 2002
Walter wrote:It occurs to me that this does fit in with the D template syntax: template Calculator(T : NUMERIC) { ... } means that T can be either NUMERIC or a class derived from NUMERIC (if NUMERIC is a class or interface). Your case 3 would be: template Cage(B, D : B) {/*whatever*/} which would constrain D to be the same as B or derived from B.I could see somebody wanting to do something like this: template List(X) { class List {...}; }; template Thingy(A, List(A).List) {...}; However, since we can't refer to template instances that way - we have to instantiate them explictly - I don't see any way to do this with the current template syntax. Do you have any ideas how?
Aug 22 2002
"Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D655282.5030402 deming-os.org...I could see somebody wanting to do something like this: template List(X) { class List {...}; }; template Thingy(A, List(A).List) {...}; However, since we can't refer to template instances that way - we have to instantiate them explictly - I don't see any way to do this with the current template syntax. Do you have any ideas how?I could see doing that with: template Thingy(A, instance List(A).List) {...};
Aug 23 2002
"Walter" <walter digitalmars.com> wrote in message news:ak757j$dr2$1 digitaldaemon.com..."Russell Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3D655282.5030402 deming-os.org...Why would you need to pass on a completely dependent type as a seperate type parameter? template Thingy(A) { alias ListType instance List(A).List; .... } But how could you write a template with two arguments, one partially dependent on the other? Is this OK? : template AdvancedList(E, F) { ... } template Thingy(A, B : instance AdvancedList(A, C)) { ... } Please correct me if wrong. I was intended to create a template whose second type argument is an instance of AdvancedList, with the restriction that this AdvancedL:ist instance should be instatiated with the "A" type as the first type parameter. I supposed that there is no type named "C". Another thing. Quoting template.html: template Bar(D, D : D[]) { } Is this valid?! You should give unique names to your type parameters. The first type parameter is called "D", and the second? Also I find bewildering the syntax: D : D[] Does this mean that the second type parameter "D" is an array composed of elements of its own type? (Infinite recursion) Yours, SandorI could see somebody wanting to do something like this: template List(X) { class List {...}; }; template Thingy(A, List(A).List) {...}; However, since we can't refer to template instances that way - we have to instantiate them explictly - I don't see any way to do this with the current template syntax. Do you have any ideas how?I could see doing that with: template Thingy(A, instance List(A).List) {...};
Aug 26 2002
"Sandor Hojtsy" <hojtsy index.hu> wrote in message news:akdcn1$1rs5$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message Why would you need to pass on a completely dependent type as a seperatetypeparameter?As a template specialization of a more general template.But how could you write a template with two arguments, one partially dependent on the other? Is this OK? : template AdvancedList(E, F) { ... } template Thingy(A, B : instance AdvancedList(A, C)) { ... }Yes.template Bar(D, D : D[]) { } Is this valid?! You should give unique names to your type parameters. The first type parameter is called "D", and the second? Also I find bewildering the syntax: D : D[] Does this mean that the second type parameter "D" is an array composed of elements of its own type? (Infinite recursion)Hmm. Perhaps I goofed <g>.
Aug 26 2002
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
Aug 21 2002
"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.It's a bit of an adjustment, but in the end I think it is superior.Is there any way to do non-type template parameters? template VectorNamespace(T, int S) { class Vector { T[S] array; } }Not directly. It can be done indirectly as part of a type, or as a class member where the class is passed as a type parameter. I thought a lot about this, and decided that non-type parameters were rare, but added a lot of complexity to the parameters, so they weren't worth supporting directly.Also, I think that you should be able to do multiple specialization: template Foo(T) { ... } template Foo(T : int, float, double) { ... }That can be faked using two templates, one instantiating the other.
Aug 21 2002
It is entirely possible that my current QWERTY -> DVORAK immersion retraining is just consuming too much of my mental flexibility quotient, but I suspect that some examples may be necessary to illustrate these solutions. This could go on a page similar to your "Converting C to D" and "Converting C++ to D", where you could show the C++ methodology and then the corresponding D methodology. MacIs there any way to do non-type template parameters? template VectorNamespace(T, int S) { class Vector { T[S] array; } }Not directly. It can be done indirectly as part of a type, or as a class member where the class is passed as a type parameter. I thought a lot about this, and decided that non-type parameters were rare, but added a lot of complexity to the parameters, so they weren't worth supporting directly.Also, I think that you should be able to do multiple specialization: template Foo(T) { ... } template Foo(T : int, float, double) { ... }That can be faked using two templates, one instantiating the other.
Aug 21 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak0m6l$2jt5$1 digitaldaemon.com...It is entirely possible that my current QWERTY -> DVORAK immersionretraining isjust consuming too much of my mental flexibility quotient, but I suspectthatsome examples may be necessary to illustrate these solutions. This couldgo ona page similar to your "Converting C to D" and "Converting C++ to D",where youcould show the C++ methodology and then the corresponding D methodology.You're quite right.
Aug 21 2002
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
Aug 22 2002
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message news:ak36kl$23os$1 digitaldaemon.com...It would also be real nice if version() statements inside the templatecouldaccess 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++.Yes, I've been thinking about that. It is a good idea, but there are many ways to do it.
Aug 23 2002
On Wed=2C 21 Aug 2002 00=3A56=3A13 -0700 =22Walter=22 =3Cwalter=40digitalmars=2Ecom=3E wrote=3A =3E www=2Edigitalmars=2Ecom=2Ftemplate=2Ehtml =3E =3E Notice how short it is =3Cg=3E=2E Ok=2C what did I miss=3F It's okay=2C but I think it could provide some more syntactic sugar=2E It would be much better if we don't need to write a separate instantiation for every template used in the program=2E Some in-place syntax would be better=2E Something like this=3A =09template Container=28T=29 =09{ =09=09class Stack =09=09{ =09=09=09private T=5B=5D pile=3B =09=09=09 =09=09=09void push=28T x=29 =09=09=09{=09 =09=09=09=09pile ~=3D x=3B =09=09=09} =09=09=09T pop=28=29 =09=09=09{ =09=09=09=09T x =3D pile=5Bpile=2Elength - 1=5D=3B =09=09=09=09pile=2Elength =3D pile=2Elength - 1=3B =09=09=09=09return x=3B =09=09=09} =09=09} =09} =09Container=28int=29=2EStack s=3B This is to avoid cluttering the namespace with continuous lists of instantiations =28which is going to happen with any large program using templates extensively=29=2E
Aug 21 2002
I hear you, but I want to try it with explicit instantiation names first. The reason is because I find templated code with lots of implicit instantiations to be totally unreadable. "Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374899452836458 news.digitalmars.com... Container(int).Stack s; This is to avoid cluttering the namespace with continuous lists of instantiations (which is going to happen with any large program using templates extensively).
Aug 21 2002
It's still explicit, it just isn't a declaration by itself, it's part of another declaration or even part of a statement. Legal wherever a typespec or field reference is legal. Sean "Walter" <walter digitalmars.com> wrote in message news:ak0qju$37o$1 digitaldaemon.com...I hear you, but I want to try it with explicit instantiation names first. The reason is because I find templated code with lots of implicit instantiations to be totally unreadable. "Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374899452836458 news.digitalmars.com... Container(int).Stack s; This is to avoid cluttering the namespace with continuous lists of instantiations (which is going to happen with any large program using templates extensively).
Aug 22 2002
I think that can work if it is prefaced by the keyword "instance". "Sean L. Palmer" <seanpalmer earthlink.net> wrote in message news:ak36qj$23r4$1 digitaldaemon.com...It's still explicit, it just isn't a declaration by itself, it's part of another declaration or even part of a statement. Legal wherever atypespecor field reference is legal. Sean "Walter" <walter digitalmars.com> wrote in message news:ak0qju$37o$1 digitaldaemon.com...first.I hear you, but I want to try it with explicit instantiation namesThe reason is because I find templated code with lots of implicit instantiations to be totally unreadable. "Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374899452836458 news.digitalmars.com... Container(int).Stack s; This is to avoid cluttering the namespace with continuous lists of instantiations (which is going to happen with any large program using templates extensively).
Aug 23 2002
On Fri=2C 23 Aug 2002 20=3A40=3A53 -0700 =22Walter=22 =3Cwalter=40digitalmars=2Ecom=3E wrote=3A =3E I think that can work if it is prefaced by the keyword =22instance=22=2E Great! So=2C we could write=3F =09instance Container=28double=29=2Edeque q=3B
Aug 24 2002
Yes. "Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374924726702083 news.digitalmars.com... On Fri, 23 Aug 2002 20:40:53 -0700 "Walter" <walter digitalmars.com> wrote:I think that can work if it is prefaced by the keyword "instance".Great! So, we could write? instance Container(double).deque q;
Aug 24 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374899452836458 news.digitalmars.com...Container(int).Stack s; This is to avoid cluttering the namespace with continuous lists of instantiations (which is going to happen with any large program using templates extensively).I forgot to mention that has syntax parsing problems, too. How about this: instance Container(int).Stack s; ?
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in news:ak0t51$k2o$1 digitaldaemon.com:"Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374899452836458 news.digitalmars.com...Just to throw it out: Stack s from instance of Container(int); or: Stack s from instance Container(int); or: Stack s instance Container(int); or: Stack s in Container(int);Container(int).Stack s; This is to avoid cluttering the namespace with continuous lists of instantiations (which is going to happen with any large program using templates extensively).I forgot to mention that has syntax parsing problems, too. How about this: instance Container(int).Stack s; ?
Aug 21 2002
On Wed, 21 Aug 2002 13:10:47 -0700 "Walter" <walter digitalmars.com> wrote:I forgot to mention that has syntax parsing problems, too. How about this: instance Container(int).Stack s; ?This is also fine!
Aug 21 2002
One possible problem with the static but multiply nameable nature of templates is that person A working on Foo.d might instantiate (to pick a template name at semi-random) Container(int) as FooCont. Person B might make Container(int) as BarCont in Bar.d. If the Container template has any variables in it, they would be somewhat like global variables. The problem is, A would think they had their own copy in FooCont and B would think theirs was safe in BarCont. Because of the description, *if* they know about each other, then they will know that these global variables are not "safe". But a Container(int) is (for sake of argument) a common thing to make, and anyone could make one at any time. You most likely would not know that someone, perhaps a library writer, had already instantiated Container(int). Since you can't ever know who else might be changing the variables inside your template instance, you can't really ever safely use those variables. If you are single threaded, you arguably could use the variables as long as you never did anything that would cause code outside of your control to execute, but that becomes more and more difficult as code becomes more object oriented. What problems would be caused by having each "equivalently parameterized" instance of a template manage their own variables? The classes/structs/enums/etc could still be shared, so that person A could pass a reference to a FooCont.SomeClass object into person B's code, where it is used as a BarCont.SomeClass object. Of course, if you do that, the FooCont.SomeClass object may be surprised when values of the Container(int) variables change when it moves into BarCont territory... Maybe template variables should just be outlawed? "const"s are fine, since nobody can change them, and they are extremely useful for configuration options. But variables just seem to be dangerous and seem to risk violating encapsulation expectations. Mac
Aug 21 2002
The problem only occurs with template variables. It's really the same issue as global variables in general, they have their uses but should normally be avoided. I can see cases where they would be useful, for example, to hold a handle to a globally shared resource. "Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak0pde$2s5j$1 digitaldaemon.com...Maybe template variables should just be outlawed? "const"s are fine,sincenobody can change them, and they are extremely useful for configurationoptions.But variables just seem to be dangerous and seem to risk violatingencapsulationexpectations.
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in news:ajvgsb$6gt$1 digitaldaemon.com:www.digitalmars.com/template.html Notice how short it is <g>. Ok, what did I miss?Templates. Cool! Does the statement "Semantic analysis is not done until instantiated." mean that the tempate will pick up variables and functions in the scope in which it is instantiated? // File: temp.d template Foo(T) { bit Bar(T a) { return a < BorgConst; } } // File alpha.d import temp; int BorgConst = 12; in Foo(int) here; here.Bar(5); // returns true If this is true it would seem to perhaps be at odds with this statement "Multiple instantiations of a TemplateDeclaration with the same TemplateParameterList all will refer to the same instantiation." Files alpha.d and bravo.d are in the same project. // File bravo.d int BorgConst = 4; in Foo(int) here; here.Bar(5); // returns false ?
Aug 21 2002
"Patrick Down" <pat codemoon.com> wrote in message news:Xns9271999977E06patcodemooncom 63.105.9.61...Does the statement "Semantic analysis is not done until instantiated." mean that the tempate will pick up variables and functions in the scope in which it is instantiated?Nope. The only thing it will pick up from the instantiation scope is the template argument types.// File: temp.d template Foo(T) { bit Bar(T a) { return a < BorgConst; } } // File alpha.d import temp; int BorgConst = 12; in Foo(int) here; here.Bar(5); // returns true If this is true it would seem to perhaps be at odds with this statement "Multiple instantiations of a TemplateDeclaration with the same TemplateParameterList all will refer to the same instantiation."Correct, which is one reason why it is false (and your example will fail to compile with a "BorgConst undefined" error). Templates are instantiated in the scope in which the template is declared. This avoids the whole C++ mess of "non-dependent names" versus "dependent names" and their subtly different lookup schemes. Clean separation between syntax and semantics is what makes this easy to do in D, and nearly impossible in C++.
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in news:ak0uas$rqn$1 digitaldaemon.com:"Patrick Down" <pat codemoon.com> wrote in message news:Xns9271999977E06patcodemooncom 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?Does the statement "Semantic analysis is not done until instantiated." mean that the tempate will pick up variables and functions in the scope in which it is instantiated?Nope. The only thing it will pick up from the instantiation scope is the template argument types.
Aug 22 2002
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; } }
Aug 22 2002
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; } }
Aug 22 2002
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?
Aug 22 2002
"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.
Aug 22 2002
Hi, "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?I would like the ability to pass constants such as literals and function pointers. For example, a smart-pointer could have a special free function given as argument. A feature I have been missing in C++, is the ability to have conditional compilation based on the concrete types. This would be useful if eg. 95% of the template code is the same, but the rest needs to be different. In some cases, it would also allow the template to provide a more efficient implementation for a specific type. Regards, Martin M. Pedersen
Aug 21 2002
Hi, "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> wrote in message news:ak0udv$sch$1 digitaldaemon.com...For example, a smart-pointer could have a special free function > given asargument. It reminds me: Smart pointers would need the ability to redefine the member operator. Is it feasible in D? Regards, Martin M. Pedersen
Aug 21 2002
"Martin M. Pedersen" <mmp www.moeller-pedersen.dk> wrote in message news:ak108p$18il$1 digitaldaemon.com...It reminds me: Smart pointers would need the ability to redefine thememberoperator. Is it feasible in D?In a garbage collected language, is there a need for smart pointers?
Aug 21 2002
Hi, "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?I'm not sure, considering try/catch/finally. But there are lots of C APIs out there returning POD structures with special free functions. fopen()/fclose() and opendir()/closedir() are simple examples of this, MAPI with MAPIFreeBuffer() is another. Even if D itself is garbage collected, many applications written in D will use such APIs, and GC will not solve all their problems. If I was to use the GC to clean up, I would need something like: interface Free { void special_free(void *); } template TSmartPointer(T, F : Free) { class SmartPointer { this(T* t) { m_t = t; } ~this() { F.special_free(m_t); } T* m_t; } } class CloseFile: Free { void special_free(void* fp) { fclose((FILE*)fp); } // I don't check the result, I know - slap me. } instance TSmartPointer fileClosing(FILE, CloseFile); FILE* fp = fopen("name", "r"); fileClosing.SmartPointer closeÍt = new fileClosing.SmartPointer(fp); ... now access it using fp Clearly, that is too tedious. try/finally would probably be a better solution... Regards, Martin M. Pedersen
Aug 21 2002
"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
Aug 21 2002
"Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak1ht1$753$1 digitaldaemon.com...The way you have D set up, you just can't do this, anyway, which Istillthink is a real pity and the thing that kills D (alongside with Java) for me. Ahem... Not that I'm not duly impressed...Even if you don't use D, I've found your comments about it to be very valuable. Are you sure that all the other neat stuff in D doesn't tempt you? <g>
Aug 21 2002
"Walter" <walter digitalmars.com> wrote in message news:ak1p2n$1ben$1 digitaldaemon.com...Even if you don't use D, I've found your comments about it to be very valuable.Thanx.Are you sure that all the other neat stuff in D doesn't tempt you?Yes, it does. But not enough to use it. It does tempt me to try and make my own language, thoguh ;-) Salutaciones, JCAB
Aug 22 2002
I've been thinking along the same lines. I'd like to see what kind of language you'd come up with. I really liked what I saw in Yoritz language, and NVIDIA Cg. Something with simplified memory management and designed to be implemented using SIMD. I have a lot of vague ideas and no time to solidify them. I'm likely to completely ditch C compatibility if I make a language, though. Too much baggage. I'd make it able to link with C but not syntactically compatible. Sean "Juan Carlos Arevalo Baeza" <jcab JCABs-Rumblings.com> wrote in message news:ak3ami$286g$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:ak1p2n$1ben$1 digitaldaemon.com...makeEven if you don't use D, I've found your comments about it to be very valuable.Thanx.Are you sure that all the other neat stuff in D doesn't tempt you?Yes, it does. But not enough to use it. It does tempt me to try andmy own language, thoguh ;-) Salutaciones, JCAB
Aug 23 2002
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message news:ak5pq2$210p$1 digitaldaemon.com...I've been thinking along the same lines. I'd like to see what kind of language you'd come up with. I really liked what I saw in Yoritzlanguage,and NVIDIA Cg. Something with simplified memory management and designedtobe implemented using SIMD. I have a lot of vague ideas and no time to solidify them.:-) Yes, I know the feeling. And I would really like to compare ideas, too. Hmmm... You know what? I think I'm going to start a little discussion list of my own on my server, to discuss this kind of thing. I'm taking the liberty of subscribing you, Sean. Anyone else interested, go here (hope this works) or drop me email: http://lists.jcabs-rumblings.com/listinfo.cgi/npl-jcabs-rumblings.com For short, the language I have in mind is: - Small C-style run-time model and language kernel. This means bit & byte manipulation, basic memory address algebra, variables & functions... With room for platform-specific additions, of course, like I/O port access, etc. - Extremely simple parser (much simpler than even D). This is, I believe, my most outrageous idea. If it works, that is. - Configurable semantics for high extensibility. Ability to create language primitives and sub-languages by programming the mapping of them into the kernel. - Compile-time execution model. - Standard library including higher-level stuff like GC, which would be optional to use.I'm likely to completely ditch C compatibility if I make a language,though.Too much baggage. I'd make it able to link with C but not syntactically compatible.I'm completely ready to ditch compatibility. I'm also working on a C/C++ parser to ease converting source code. Salutaciones, JCAB
Aug 23 2002
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
Aug 22 2002
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.
Aug 22 2002
In article <ak32sg$1v7v$1 digitaldaemon.com>, Walter says...Your comments on smart handles in D explain it better than I have. Mind if I plagairize it a bit?I would be honored.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.I know that 'counted' would increase the complexity of the compiler, which you have been trying to avoid, but I think it could be done without too much additional effort. (I am not, however, familiar with writing compilers, so my assumptions could be vastly incorrect) It would certainly take less effort to get it right (ignoring issues of "completely optimized" for the time being) inside the compiler than it does outside. Mac
Aug 22 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak3agl$27qt$1 digitaldaemon.com...I know that 'counted' would increase the complexity of the compiler, whichyouhave been trying to avoid, but I think it could be done without too much additional effort. (I am not, however, familiar with writing compilers,so myassumptions could be vastly incorrect) It would certainly take lesseffort toget it right (ignoring issues of "completely optimized" for the timebeing)inside the compiler than it does outside.The complexity comes from decrementing the counts of objects going out of scope, in the presence of exceptions. It did occur to me that if this was supported, it would also implicitly support the people who want deterministic destruction.
Aug 23 2002
In article <ak5rgs$23m5$1 digitaldaemon.com>, Walter says..."Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak3agl$27qt$1 digitaldaemon.com...[clip]I know that 'counted' would increase the complexity of the compiler, whichyouThe complexity comes from decrementing the counts of objects going out of scope, in the presence of exceptions. It did occur to me that if this was supported, it would also implicitly support the people who want deterministic destruction.Yup. Actually, I originally started thinking about a 'scoped' keyword whose sole purpose was to supply scoped destruction, but then I got to thinking about the times when you might want to make a new thing and pass it out of a function, but you still wanted its resources cleaned up as quickly as possible. So I started thinking about reference counting and realized that it would handle the 'scoped' behavior as a trivial case. Made me happy... Mac
Aug 23 2002
"Mac Reiter" <Mac_member pathlink.com> wrote in message news:ak5v0i$277b$1 digitaldaemon.com...Yup. Actually, I originally started thinking about a 'scoped' keywordwhosesole purpose was to supply scoped destruction, but then I got to thinkingaboutthe times when you might want to make a new thing and pass it out of afunction,but you still wanted its resources cleaned up as quickly as possible. SoIstarted thinking about reference counting and realized that it wouldhandle the'scoped' behavior as a trivial case. Made me happy...It's pretty cool when solving one problem provides a trivial solution to an apparently unrelated problem.
Aug 23 2002
On Thu, 22 Aug 2002 15:29:07 +0000 (UTC) Mac Reiter <Mac_member pathlink.com> wrote: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.Note that if GC will still run on refcounted objects as well, it provides a solution (or sort of) - such cases will get resolved (and destructors will be called), but not immediately...
Aug 22 2002
Thank you. I meant to illustrate reference counting as a means of minimizing reclamation latency, but relying on garbage collection as the final means of ensuring correctness/completeness of de-allocation. Somewhere along the way I forgot to state that clearly... Guess I ramble too much. I just wanted to make sure that nobody thought "Hey, reference counting gives quick reclamation! Why don't we just use that instead of this garbage collection system?" I prefer the combination so that you can take advantages of the strengths of each system. Mac In article <CFN374909677284259 news.digitalmars.com>, Pavel Minayev says...On Thu, 22 Aug 2002 15:29:07 +0000 (UTC) Mac Reiter <Mac_member pathlink.com> wrote: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.Note that if GC will still run on refcounted objects as well, it provides a solution (or sort of) - such cases will get resolved (and destructors will be called), but not immediately...
Aug 22 2002
"Martin M. Pedersen" <mmp www.moeller-pedersen.dk> wrote in message news:ak0udv$sch$1 digitaldaemon.com...I would like the ability to pass constants such as literals and function pointers. For example, a smart-pointer could have a special free function given as argument.I've thought about this. Wouldn't it make sense to have an argument that is an interface, the implementation of which has the desired special free function? interface Free { void special_free(void *); } template Foo(T, U : Free) { ... U.special_free(p); ... } class Bar : Free { void special_free(void *p) { ... } } instance Foo(int, Bar) abc;A feature I have been missing in C++, is the ability to have conditional compilation based on the concrete types. This would be useful if eg. 95%ofthe template code is the same, but the rest needs to be different. In some cases, it would also allow the template to provide a more efficient implementation for a specific type.This would be a valuable feature, but there are many different ways to do it. I haven't gone far down the path of exploring them.
Aug 21 2002
Hi, "Walter" <walter digitalmars.com> wrote in message news:ak119a$1ga1$1 digitaldaemon.com...I've thought about this. Wouldn't it make sense to have an argument thatisan interface, the implementation of which has the desired special free function?That would do it, I think :-)My solution to the missing feature in C++, has sometimes been to use overloaded functions outside the template, but I have also resorted to not using a template at all, but auto-generate classes instead by some special preprocessing. Regards, Martin M. PedersenA feature I have been missing in C++, is the ability to have conditional compilation based on the concrete types.This would be a valuable feature, but there are many different ways to do it. I haven't gone far down the path of exploring them.
Aug 21 2002
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?
Aug 22 2002
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!
Aug 22 2002
I though of another extention to that idea. How about if there is a collision (overload), the user would have to do this... import max(int) import max(float) int.max(a,b); float.max(x,y); That way it's simular to how D handles other overloading. PS I haven't been able to use this newgroup for a while, my computer crashed and I've spent several days repairing it. Darn XP. "Pavel Minayev" <evilone omen.ru> wrote in message news:CFN374907807516898 news.digitalmars.com...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!
Aug 27 2002
(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?
Aug 22 2002
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.Itthus 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 currentnamespaceusing 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 todo theequivalent of a scope resolution at every usage to tell the compiler whatto do(since *all* of the names would have collided), you might as well havejust donethat and skipped the 'using' step. If you brought in different pieces of the same template, but fromdifferentinstantiations: using foo(int).Max; using foo(double).Min; then there would be no namespace collision, and it might be allowable.Horriblyconfusing, in the example given above, but possibly useful in somesituations...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 templateanddidn't want to have to precede every template member usage with 'intfoo.'. Trying to extend the usage beyond that, however, causes more problems thanitsolves. Which leads me to my favorite solution so far, and it is even already inthelanguage (at least in the syntax, even if the template usage of it may notbe inthe 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 amemberwill win), and just generally seems nice and clean to me... That may bemyVisual Basic experience coming back to me (VB also uses 'with', and youuse it aLOT when you start getting OOPed in VB). Mac
Aug 22 2002
On Thu=2C 22 Aug 2002 14=3A46=3A31 +0000 =28UTC=29 Mac Reiter =3CMac=5Fmember=40pathlink=2Ecom=3E wrote=3A =3E If you attempted to bring in entire multiple instantiations of the same =3E template=2C that could probably just be outlawed=2E Since you would have to do the =3E equivalent of a scope resolution at every usage to tell the compiler what to do =3E =28since *all* of the names would have collided=29=2C you might as well have just done =3E that and skipped the 'using' step=2E I don't think it is an error=2E=2E=2E you should just get two versions of the same function=2C just if it was overloaded=3A =09using Min=28int=29=3B =09using Min=28double=29=3B =09int a=2C b=3B =09double c=2C d=3B =09x =3D min=28a=2C b=29=3B=09=2F=2F Min=28int=29=2Emin =09y =3D min=28c=2C d=29=3B=09=2F=2F Min=28double=29=2Emin
Aug 22 2002
Sounds good "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.Itthus 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 currentnamespaceusing 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 todo theequivalent of a scope resolution at every usage to tell the compiler whatto do(since *all* of the names would have collided), you might as well havejust donethat and skipped the 'using' step. If you brought in different pieces of the same template, but fromdifferentinstantiations: using foo(int).Max; using foo(double).Min; then there would be no namespace collision, and it might be allowable.Horriblyconfusing, in the example given above, but possibly useful in somesituations...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 templateanddidn't want to have to precede every template member usage with 'intfoo.'. Trying to extend the usage beyond that, however, causes more problems thanitsolves. Which leads me to my favorite solution so far, and it is even already inthelanguage (at least in the syntax, even if the template usage of it may notbe inthe 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 amemberwill win), and just generally seems nice and clean to me... That may bemyVisual Basic experience coming back to me (VB also uses 'with', and youuse it aLOT 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?
Aug 28 2002