digitalmars.D - D's limited template specialization abilities compared to C++
- Ahuzhgairl (26/26) May 25 2013 Hi,
- Ahuzhgairl (2/2) May 25 2013 By extension,
- Peter Alexander (14/14) May 25 2013 Is this what you're looking for?
- Ahuzhgairl (16/16) May 25 2013 No,
- Ahuzhgairl (8/8) May 25 2013 Uneditable newsgroups. Simplest case.
- Peter Alexander (13/21) May 25 2013 Two problems with that:
- Kenji Hara (12/20) May 25 2013 It would work.
- Ahuzhgairl (16/16) May 25 2013 C++ example, works:
- Peter Alexander (10/25) May 25 2013 As we've shown, you can do this in D. Instead of template
- Kenji Hara (26/42) May 25 2013 As I already shown, Baz!(Bar!(int)); could work in D.
- Ahuzhgairl (22/22) May 25 2013 Kenji,
- Kenji Hara (26/46) May 25 2013 Hmm. Currently D can specify specType for alias template parameter.
- Ahuzhgairl (7/7) May 25 2013 Kenji, thanks again for understanding exactly what I meant.
- Manu (26/33) May 26 2013 I presume this is Ndit from IRC?
- Andrej Mitrovic (3/5) May 26 2013 This feature is news to me! Pretty cool.
- Timon Gehr (6/12) May 26 2013 I'm about 3/4 through a D frontend implementation and was unaware of
- Andrej Mitrovic (2/4) May 27 2013 I wonder how many other easter eggs there are in the language. :p
- deadalnix (13/40) May 25 2013 Hi, I obviously don't know D that much, but I assume I do.
-
Joshua Niehus
(3/5)
May 25 2013
- Andrei Alexandrescu (11/21) May 25 2013 A great thing about this community is it being nice and helpful to
Hi, In D, the : in a template parameter list only binds to 1 parameter. There is no way to specialize upon the entire template parameter list. Therefore you can't do much with the pattern matching and it's not powerful. Not a reasonable situation for a language aiming to be only the best. What is needed is the ability to bind to the whole template parameter list: template <class> struct get_class; template <class R, class C, class... A> struct get_class<R (C::*)(A...)> { typedef C type; }; Let's shorten the terms: <R, C, A...> <R (C::*)(A...)> And here's how this kind of specialization would work in D: template A[B] { struct C {} } template Foo[alias X, Y, Z X[Y].Z] { alias Z Foo; } void main() { alias Foo[A[bool].C] xxx; } You need a separate delimiter besides : which does not bind to individual parameters, but which binds to the set of parameters. I propose as the character which shall be the delimiter for the arguments to the pattern match, and the pattern match. On an unrelated note, I don't like the ! thing so I use []. Sorry for the confusion there. z
May 25 2013
By extension, template Foo[X, Y, Z X[Y], Y[Z]] { alias Y Foo; }
May 25 2013
Is this what you're looking for? struct Foo(T) { static void bar() { writeln("general"); } } struct Foo(T : A[B], A, B) { static void bar() { writeln("special"); } } void main() { Foo!(int).bar(); // general Foo!(int[int]).bar(); // special }
May 25 2013
No, struct Foo(T) { static void f() { writeln("general"); } } struct Foo(T : A(B).alias C, A, B, C) { static void f() { writeln("special"); } } struct Bar(T) { struct Baz {} } struct Baz(T : A(B), A, B) { } void main() { Foo!(Bar!(int).Baz); Baz!(Bar!(int)); }
May 25 2013
Uneditable newsgroups. Simplest case. struct Bar(T) {} struct Foo(T : A(B), A, B) { static void f() {} } void main() { Foo!(Bar!(int)).f(); }
May 25 2013
On Saturday, 25 May 2013 at 12:13:42 UTC, Ahuzhgairl wrote:Uneditable newsgroups. Simplest case. struct Bar(T) {} struct Foo(T : A(B), A, B) { static void f() {} } void main() { Foo!(Bar!(int)).f(); }Two problems with that: 1. A(B) should be A!(B) 2. A won't bind to Bar because Bar is not a type, it is a template. A should be an alias. This works: struct Bar(T) {} struct Foo(T : A!(B), alias A, B) { static void f() {} } void main() { Foo!(Bar!(int)).f(); }
May 25 2013
2013/5/25 Ahuzhgairl <bulletproofchest gmail.com>Uneditable newsgroups. Simplest case. struct Bar(T) {} struct Foo(T : A(B), A, B) { static void f() {} } void main() { Foo!(Bar!(int)).f(); }It would work. struct Bar(T) {} struct Foo(T : A!(B), alias A, B) { // 1, 2 static void f() {} } void main() { Foo!(Bar!(int)).f(); } 1. should use A!(B), instead of A(B) 2. A would match to template, so should receive by TemplateAliasParameter. Kenji Hara
May 25 2013
C++ example, works: template <class> struct A; template <template <class> class X, class Y> struct A<X<Y>> {}; template <class> struct B; int main() { A<B<int>> a; } But the following does not work: struct Foo {}; template <class> struct B { Foo x; } template <nontype P> struct A; template <auto M, auto C, nontype P> struct A<M C::*P> {} int main() { A<&B<int>::x> a; } D should be able to do both.
May 25 2013
On Saturday, 25 May 2013 at 12:43:42 UTC, Ahuzhgairl wrote:C++ example, works: template <class> struct A; template <template <class> class X, class Y> struct A<X<Y>> {}; template <class> struct B; int main() { A<B<int>> a; }As we've shown, you can do this in D. Instead of template templates, you use alias.But the following does not work: struct Foo {}; template <class> struct B { Foo x; } template <nontype P> struct A; template <auto M, auto C, nontype P> struct A<M C::*P> {} int main() { A<&B<int>::x> a; }It's getting very hard to see what you're trying to do. I think it would help if you used real C++ and D syntax instead of inventing new syntax because I can't tell what you're trying to achieve and what semantics you expect of it. Please post a small example of real, working, compilable C++ that shows what you want to do, and we'll show you how to do it in D (assuming it is possible).
May 25 2013
2013/5/25 Ahuzhgairl <bulletproofchest gmail.com>No, struct Foo(T) { static void f() { writeln("general"); } } struct Foo(T : A(B).alias C, A, B, C) { static void f() { writeln("special"); } } struct Bar(T) { struct Baz {} } struct Baz(T : A(B), A, B) { } void main() { Foo!(Bar!(int).Baz); Baz!(Bar!(int)); }As I already shown, Baz!(Bar!(int)); could work in D. But, currently Foo!(Bar!(int).Baz); is not yet supported. I'm opening a compiler enhancement for related case, http://d.puremagic.com/issues/show_bug.cgi?id=9022 and right now I updated compiler patch to allow parameterize enclosed type by name/type/alias. https://github.com/D-Programming-Language/dmd/pull/1296 https://github.com/9rnsr/dmd/commit/b29726d30b0094b9e7c2e15f5802501cb686ee68 After it is merged, you can write it as follows. import std.stdio; struct Foo(T) { static void f() { writeln("general"); } } struct Foo(T : A!(B).C, alias A, B, alias C) { static void f() { writeln("special"); } } struct Bar(T) { struct Baz {} } void main() { Foo!(Bar!(int).Baz) x; x.f(); // prints "special" } Kenji Hara
May 25 2013
Kenji, Thank you much for the '.C' alias support, Amazed to see there could be some action so quick! Could we please look at the nontype-as-primary-template? How can we deduce all of the dependent types from a non-type template parameter, if it's the only parameter of the primary template? struct Foo {}; template <class> struct B { Foo x; } template <nontype P> struct A; // P is the primary-template param template <auto M, auto C, nontype P> struct A<M C::*P> { // Given the call in main, // M is deduced as Foo // C is deduced as B<int> // P was passed successfully and we know the types that make it up. } int main() { auto mp = &B<B<int>>::x A<mp> a; }
May 25 2013
2013/5/26 Ahuzhgairl <bulletproofchest gmail.com>Kenji, Thank you much for the '.C' alias support, Amazed to see there could be some action so quick! Could we please look at the nontype-as-primary-template? How can we deduce all of the dependent types from a non-type template parameter, if it's the only parameter of the primary template? struct Foo {}; template <class> struct B { Foo x; } template <nontype P> struct A; // P is the primary-template param template <auto M, auto C, nontype P> struct A<M C::*P> { // Given the call in main, // M is deduced as Foo // C is deduced as B<int> // P was passed successfully and we know the types that make it up. } int main() { auto mp = &B<B<int>>::x A<mp> a; }Hmm. Currently D can specify specType for alias template parameter. struct X(alias int x) {} // matches only when the symbol x has the type int void main() { int a; X!a xa; // match OK long b; X!b xb; // match NG } But, compiler does not allow parameterize of specType. struct Foo {} struct B(T) { static Foo x; } //struct A(alias P) {} struct A(alias M* P, M) // matches only when the symbol P has the type M* //struct A(alias C.M* P, M, C) { } void main() { auto mp = &B!(B!int).x; A!mp a; // does not match... } I think it should be allowed. Kenji Hara
May 25 2013
Kenji, thanks again for understanding exactly what I meant. I am a big fan of template features. I seriously hope D can do this in the future- the inability of the *template system* to deduce information about non-types is one of the big holes in C++: We can deduce information at function scope, yet the templates cannot do it! This is a strange imbalance of nature.
May 25 2013
On 26 May 2013 16:41, Ahuzhgairl <bulletproofchest gmail.com> wrote:Kenji, thanks again for understanding exactly what I meant. I am a big fan of template features. I seriously hope D can do this in the future- the inability of the *template system* to deduce information about non-types is one of the big holes in C++: We can deduce information at function scope, yet the templates cannot do it! This is a strange imbalance of nature.I presume this is Ndit from IRC? The part that breaks my mind, is that you appeared professing you were missing requirements for realtime critical software (and significantly more realtime critical than my own work apparently), but then you became the most obscure template crazed dude I've ever seen. In my experience, the 2 are fundamentally incompatible. A realtime programmer with requirements as strict as you claim, would avoid intensive (ab)use of templates like the plague! :/ It really seems like you're just trying to break D in whichever way you can (and having some trouble). And now in 3 cases, where you have successfully 'broken' D, a helpful member from the community has taken it upon themselves to help you and give you what you want. Have you actually tried working with D templates for a while. Templates are, hands down, the strongest and most compelling feature of D. If you actually use D for a short time, you will realise this. Now, I tend to think the level of support shown to you is spectacular, taking entire days of peoples time. Especially considering you've never managed to produce an actual use cased for anything you've come up with. But I'd like to make a suggestion that you actually USE D for a while, and waste peoples time with REAL USE CASES where you find that your needs are not satisfied. D is a volunteer community, if you never plan to use these improvements, and nobody else ever does, then you're effectively wasting their time, which is a little unfair.
May 26 2013
On 5/26/13, Kenji Hara <k.hara.pg gmail.com> wrote:Hmm. Currently D can specify specType for alias template parameter. struct X(alias int x) {} // matches only when the symbol x has the type intThis feature is news to me! Pretty cool. Philippe Sigaud: Is this mentioned in the D Template book?
May 26 2013
On 05/26/2013 03:04 PM, Andrej Mitrovic wrote:On 5/26/13, Kenji Hara <k.hara.pg gmail.com> wrote:I'm about 3/4 through a D frontend implementation and was unaware of this. :) The reason is that the feature is undocumented. (The grammar specification mentions the syntax, though.)Hmm. Currently D can specify specType for alias template parameter. struct X(alias int x) {} // matches only when the symbol x has the type intThis feature is news to me! Pretty cool.Philippe Sigaud: Is this mentioned in the D Template book?I don't think so.
May 26 2013
On 5/27/13, Timon Gehr <timon.gehr gmx.ch> wrote:The reason is that the feature is undocumented. (The grammar specification mentions the syntax, though.)I wonder how many other easter eggs there are in the language. :p
May 27 2013
On Saturday, 25 May 2013 at 10:46:05 UTC, Ahuzhgairl wrote:Hi, In D, the : in a template parameter list only binds to 1 parameter. There is no way to specialize upon the entire template parameter list. Therefore you can't do much with the pattern matching and it's not powerful. Not a reasonable situation for a language aiming to be only the best. What is needed is the ability to bind to the whole template parameter list: template <class> struct get_class; template <class R, class C, class... A> struct get_class<R (C::*)(A...)> { typedef C type; }; Let's shorten the terms: <R, C, A...> <R (C::*)(A...)> And here's how this kind of specialization would work in D: template A[B] { struct C {} } template Foo[alias X, Y, Z X[Y].Z] { alias Z Foo; } void main() { alias Foo[A[bool].C] xxx; } You need a separate delimiter besides : which does not bind to individual parameters, but which binds to the set of parameters. I propose as the character which shall be the delimiter for the arguments to the pattern match, and the pattern match. On an unrelated note, I don't like the ! thing so I use []. Sorry for the confusion there. zHi, I obviously don't know D that much, but I assume I do. I have this feature that I can't even show a working example that exists in C++. I also can't come up with any use case, but I know this is mandatory to have. As I assume I know D well enough, I assume I know that this is impossible in D, so I propose an improvement. With that improvement, a new syntax is introduced to support some new feature that is barely defined and it can be used in unknown situation. I also explain myself using my own made up syntax. I don't care if it conflict with other language construct as it is superior anyway.
May 25 2013
On Saturday, 25 May 2013 at 16:27:59 UTC, deadalnix wrote:Hi, I obviously don't know D that much, but I assume I do. [..snip..]<chuckle> +1
May 25 2013
On 5/25/13 12:27 PM, deadalnix wrote:Hi, I obviously don't know D that much, but I assume I do. I have this feature that I can't even show a working example that exists in C++. I also can't come up with any use case, but I know this is mandatory to have. As I assume I know D well enough, I assume I know that this is impossible in D, so I propose an improvement. With that improvement, a new syntax is introduced to support some new feature that is barely defined and it can be used in unknown situation. I also explain myself using my own made up syntax. I don't care if it conflict with other language construct as it is superior anyway.A great thing about this community is it being nice and helpful to newcomers. (That said, I had a good chuckle - I've seen this pattern before.) To the OP: you may want to look into template constraints, they're much easier to define and use than pattern matching in template arguments. Also, aliases are quite a bit more convenient and general than C++'s template template arguments, which run completely amok at the third regression: template<template<template <class> class> class T> class C; Andrei
May 25 2013