digitalmars.D.learn - Partial template function specialization
- Peter Alexander (15/15) Aug 19 2009 Hey all,
- Simen Kjaeraas (10/17) Aug 20 2009 T foo( T, U )( U value ) {...}
- Peter Alexander (7/17) Aug 20 2009 Not quite sure what's going on there, but it doesn't look like what I wa...
- Lars T. Kyllingstad (3/8) Aug 20 2009 Man, we just got the ETA on D2... :)
- bearophile (7/12) Aug 20 2009 I think that was partial specialization, but the name was indeed differe...
- Lutger (21/21) Aug 20 2009 You can also do this with template constraints in D2:
- Lars T. Kyllingstad (42/62) Aug 20 2009 You've come to the right place. D's template specialisation is very
- Lars T. Kyllingstad (6/8) Aug 20 2009 What I meant was: I don't know how common *templated* function
- Peter Alexander (12/24) Aug 20 2009 Excellent! Thanks a lot. I was hoping that D could overcome this problem...
- Steven Schveighoffer (16/47) Aug 20 2009 The module system is the way to get comparable, if not equivalent,
- Bill Baxter (15/39) Aug 20 2009 D1.
- Jarrett Billingsley (8/18) Aug 20 2009 they are an atrocity in language design), so I create global functions f...
- Sato. E. (10/17) Aug 20 2009 Field norm(Field, V)(V v) {
Hey all, I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations. For example, you can create something like this: template <class Field, class V> const Field norm(const V& v); and you can specialize it: template <> const double norm(const double& d) { return d < 0.0 ? -d : d; } but you can't partially specialize it: template <class Field> const Field norm(const Vector3<Field>& v) { /* return sqrt( ... ) */ } Unless I'm mistaken... Also, while I'm here. Does D have any macro support? I know it doesn't have pre-processor macros, but something like Nemerle's macros would be really, really nice. Thanks in advance.
Aug 19 2009
Peter Alexander wrote:Hey all, I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations.T foo( T, U )( U value ) {...} template fooPartial( T ) { alias foo!( T, int ) fooPartial; } This may or may not have been what you want.Also, while I'm here. Does D have any macro support? I know it doesn't have pre-processor macros, but something like Nemerle's macros would be really, really nice.Macros are currently scheduled for D3. In the meantime, you can do just about anything with string mixins and CTFE. -- Simen
Aug 20 2009
Simen Kjaeraas Wrote:T foo( T, U )( U value ) {...} template fooPartial( T ) { alias foo!( T, int ) fooPartial; } This may or may not have been what you want.Not quite sure what's going on there, but it doesn't look like what I want. I want a general function: T foo(T, U)(U value) and one specialized for when U = Vector3!(T) Also, it's important that the original and the specialization have the same function name, otherwise it's not really generic at all.Macros are currently scheduled for D3. In the meantime, you can do just about anything with string mixins and CTFE.Cool. Is there any sort of ETA on D3?
Aug 20 2009
Peter Alexander wrote:Simen Kjaeraas Wrote:Man, we just got the ETA on D2... :) -LarsMacros are currently scheduled for D3. In the meantime, you can do just about anything with string mixins and CTFE.Cool. Is there any sort of ETA on D3?
Aug 20 2009
Peter Alexander:I want a general function: T foo(T, U)(U value) and one specialized for when U = Vector3!(T) Also, it's important that the original and the specialization have the same function name, otherwise it's not really generic at all.I think that was partial specialization, but the name was indeed different. Templates once instantiated produce all different functions, so when you instantiate them you have the same gains coming from partial instantiation. If you want a single name for both templates you can probably do that too, you may need a third template with a different type that a compile-time uses one or the other version of the template, in D2 you can also use template constraints. If you show me your use case there's probably some way to solve your problem, I have found D templates quite flexible.Cool. Is there any sort of ETA on D3?<It may be possible that some of my words have changed Walter's mind, so macros will not be seen in D. Bye, bearophile
Aug 20 2009
You can also do this with template constraints in D2: template foo(T, U) if ( is(T == int) ) { void foo(T t, U u) { //t is int } } template foo(T, U) if ( is(T == string) ) { void foo(T t, U u) { //t is string } } IFTI still works here: foo("bla", 1) and foo(1,1) are both valid You can do almost anything in the if condition (constraint) that can evaluate to bool at compile time. See std.traits and the __traits keywords for useful stuff.
Aug 20 2009
Peter Alexander wrote:Hey all, I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations. For example, you can create something like this: template <class Field, class V> const Field norm(const V& v); and you can specialize it: template <> const double norm(const double& d) { return d < 0.0 ? -d : d; } but you can't partially specialize it: template <class Field> const Field norm(const Vector3<Field>& v) { /* return sqrt( ... ) */ } Unless I'm mistaken...You've come to the right place. D's template specialisation is very powerful, and when combined with implicit function template instantiation (IFTI) it makes for really beautiful code. Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so I'll give my answer in D2 code. It is highly likely it will also work in D1. First of all, I don't know how it is in C++, but in D you rarely write function declarations without definitions. So unless you have a very general function body for your "general case", I'd simply drop it. If you have, the general case looks like this: Field norm(Field, V)(ref V v) { ... } // To call it: SomeDoublePrecisionVector v = ...; double n = norm!(double, SomeDoublePrecisionVector)(v); Actually, because of IFTI, you can probably call it like double n = norm!(double)(v); but there is a chance that the compiler will find it too much like the partially specialised case below. The completely specialised case will look like this: double norm()(double d) { return d < 0.0 ? -d : d; } // To call it: double n = norm(-3.0); Note that in the not-too-far future it is likely that non-templated functions will be allowed to overload against templated functions. When that happens, you can drop the first set of parentheses in the declaration. I would write the partially specialised case like this: Field norm(Field)(ref Vector3!(Field) v) { ... } // To call it: Vector3!(real) myVector; real n = norm(myVector); Yes, the compiler is smart enough to extract the Field from the Vector3!(Field) type. :) Because of IFTI you don't even have to specify it when calling norm(). In the above I have at least tried to stay D1 compatible. In D2 you can (arguably, of course) beautify your code a bit by writing Vector3!Float and so on. The parentheses are only needed when there are several template parameters. For more info, check out http://www.digitalmars.com/d/2.0/template.html -Lars
Aug 20 2009
Lars T. Kyllingstad wrote:First of all, I don't know how it is in C++, but in D you rarely write function declarations without definitions.What I meant was: I don't know how common *templated* function declarations are. I know C++ programmers tend to put the declaration in one place and the definition in an entirely different place. One of the annoying things of C++ that D fixes, IMHO. -Lars
Aug 20 2009
Lars T. Kyllingstad Wrote:Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so I'll give my answer in D2 code. It is highly likely it will also work in D1.I'm using neither :) I'm just considering learning at the moment.First of all, I don't know how it is in C++, but in D you rarely write function declarations without definitions. So unless you have a very general function body for your "general case", I'd simply drop it. If you have, the general case looks like this: <snip> For more info, check out http://www.digitalmars.com/d/2.0/template.html -LarsExcellent! Thanks a lot. I was hoping that D could overcome this problem. Ah, one (maybe) final question: Is there an equivalent to friends in D (didn't see any in the docs)? If so, do they work with templates easily? In my style of programming, I very rarely use member functions (I think they are an atrocity in language design), so I create global functions for almost everything, and when they need to access to private members, I have the class declare the function as a friend. Does D support my style of programming? Here's a concrete example of something I'd like to do (pseudocode): class Foo { private int x; friend globalFun; } class Bar { private int y; friend globalFun; } void globalFun(ref Foo foo, ref Bar bar) { foo.x = bar.y; } Is there anything like this in D? Export sounds like the right thing, but can that be used in the example above, assuming that Foo and Bar are in separate modules?
Aug 20 2009
On Thu, 20 Aug 2009 10:22:00 -0400, Peter Alexander <peter.alexander.au gmail.com> wrote:Lars T. Kyllingstad Wrote:The module system is the way to get comparable, if not equivalent, behavior. Any functions or classes declared in the same module are automatically friends with eachother. The idea behind it is that a single module is generally developed as a group of related items, and so the functions existing in the same module usually know the internals of the objects inside the module. Plus the author of such functions obviously has access to the source code, and generally is the author of the objects.Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so I'll give my answer in D2 code. It is highly likely it will also work in D1.I'm using neither :) I'm just considering learning at the moment.First of all, I don't know how it is in C++, but in D you rarely write function declarations without definitions. So unless you have a very general function body for your "general case", I'd simply drop it. If you have, the general case looks like this: <snip> For more info, check out http://www.digitalmars.com/d/2.0/template.html -LarsExcellent! Thanks a lot. I was hoping that D could overcome this problem. Ah, one (maybe) final question: Is there an equivalent to friends in D (didn't see any in the docs)? If so, do they work with templates easily?In my style of programming, I very rarely use member functions (I think they are an atrocity in language design), so I create global functions for almost everything, and when they need to access to private members, I have the class declare the function as a friend. Does D support my style of programming?Yes, global functions declared in the same module of the class have full access to private variables.Here's a concrete example of something I'd like to do (pseudocode): class Foo { private int x; friend globalFun; } class Bar { private int y; friend globalFun; } void globalFun(ref Foo foo, ref Bar bar) { foo.x = bar.y; } Is there anything like this in D? Export sounds like the right thing, but can that be used in the example above, assuming that Foo and Bar are in separate modules?You would have to put Foo and Bar in the same module along with globalFun, or declare their members as package, and put their modules in the same package. -Steve
Aug 20 2009
On Thu, Aug 20, 2009 at 7:22 AM, Peter Alexander<peter.alexander.au gmail.com> wrote:Lars T. Kyllingstad Wrote:D1.Disclaimer: You didn't say whether you use D1 or D2, but I use D2, so I'll give my answer in D2 code. It is highly likely it will also work in=I'm using neither :) =A0I'm just considering learning at the moment.o, do they work with templates easily?First of all, I don't know how it is in C++, but in D you rarely write function declarations without definitions. So unless you have a very general function body for your "general case", I'd simply drop it. If you have, the general case looks like this: =A0<snip> For more info, check out http://www.digitalmars.com/d/2.0/template.html -LarsExcellent! Thanks a lot. I was hoping that D could overcome this problem. Ah, one (maybe) final question: Is there an equivalent to friends in D (didn't see any in the docs)? If s=In my style of programming, I very rarely use member functions (I think t=hey are an atrocity in language design), so I create global functions for a= lmost everything, and when they need to access to private members, I have t= he class declare the function as a friend.Does D support my style of programming?Instead of friend, in D everything within one file (=3D=3Done module) has access to everything else in that same file/module. So you can use your style, as long as you put the global functions in the same module as the classes operated on.Here's a concrete example of something I'd like to do (pseudocode): class Foo { private int x; friend globalFun; } class Bar { private int y; friend globalFun; } void globalFun(ref Foo foo, ref Bar bar) { foo.x =3D bar.y; } Is there anything like this in D? Export sounds like the right thing, but=can that be used in the example above, assuming that Foo and Bar are in se= parate modules? I don't think export has anything to do with it. --bb
Aug 20 2009
On Thu, Aug 20, 2009 at 10:34 AM, Bill Baxter<wbaxter gmail.com> wrote:On Thu, Aug 20, 2009 at 7:22 AM, Peter Alexander<peter.alexander.au gmail.com> wrote:they are an atrocity in language design), so I create global functions for = almost everything, and when they need to access to private members, I have = the class declare the function as a friend.Lars T. Kyllingstad Wrote: In my style of programming, I very rarely use member functions (I think =Alternatively, you can mark the data members 'package', and then any functions in the same package can access them. But keep in mind that 'package' is limited in that you can't access those members from sub-packages, meaning you are forced into a flat package hierarchy.Does D support my style of programming?Instead of friend, in D everything within one file (=3D=3Done module) has access to everything else in that same file/module. So you can use your style, as long as you put the global functions in the same module as the classes operated on.
Aug 20 2009
Peter Alexander Wrote:Hey all, I'm considering learning D at the moment, and one thing that has bothered me in C++ is the lack of partial template function specializations. For example, you can create something like this: template <class Field> const Field norm(const Vector3<Field>& v) { /* return sqrt( ... ) */ } Thanks in advance.Field norm(Field, V)(V v) { ... } Field norm(Field, V : Vector3!(Field))(ref V v) { ... } --- auto v = new Vector3!(float) norm!(float)(v)
Aug 20 2009