digitalmars.D - Template metaprogramming quirk list
- Don Clugston (94/94) Jan 17 2006 The items in this list mostly fall into the category of limitations
- Georg Wrede (17/133) Jan 19 2006 This is drastically different from what I've been (all year) talking
- Sean Kelly (5/10) Jan 20 2006 I've run into most of the problems Don describes and I agree with all of...
- Walter Bright (7/11) Jan 21 2006 On the 17th and 18th I attended a conference, and on the 18th I was givi...
- Georg Wrede (2/16) Jan 22 2006 Cool!!!
- Chris Lajoie (4/5) Jan 20 2006 signed. most of these seem like relatively minor things but I would
The items in this list mostly fall into the category of limitations rather than bugs; but in each case, the limitations are unintuitive. I've listed them in order of decreasing importance. Workarounds are also shown. --------------------- MAJOR: Restrictions on static if in templates Quoting the docs: "StaticIfConditions cannot appear at module scope. They can appear in class, template, struct, union, or function scope. In function scope, the symbols referred to in the AssignExpression can be any that can normally be referenced by an expression at that point. Otherwise, the only symbols that can be referred to are up one scope level from the condition." ... "It does not introduce a new scope even if { } are used for conditionally compiled statements." Together, these restrictions mean that a metafunction can't store intermediate results, so that complex template code like pragma's regex gets quite ugly and convoluted. Workaround: invoke the metafunction every time you want to use the result from it. (Sometimes this can result in a drastic increase in the number of template instantiations required). --------------------- MINOR: Allow concatenation char[] ~ char Desired: const char [] s = "abcdef" ~ 'g'; Workaround: Ugly. Convert char to char[] by taking slices of a string containing all characters. Only works for char, not for wchar, dchar. const char [] s = "abcdef" ~ makechar!('g'); /// converts a single char to a char[] template makechar(int c) { const char [] makechar= x"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a1b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"[c..c+1]; } --------------------- AESTHETIC: The . in recursive templates. template fact(int x) { static if (x>1) const int fact = x * .fact!(x-1); else const int fact = 1; } The dot is a workaround, only needed because the constant "fact" we're setting is in scope. Why is it already in the symbol table? The workaround is more complex when the template is not at module scope -- you need to include dot plus fully qualified name. The following example works: struct outer { template fact(int x) { static if (x>1) const int fact = x * .outer.fact!(x-1); else const int fact = 1; } static assert(fact!(6)==8); } If you leave off the dot before the outer, ie static if (x>1) const int fact = x * outer.fact!(x-1); then the error message is: template fact!(x - 1) is not a member of outer which is a little weird. --------------------- MINOR: Allow compile time equality comparisions char[] == char[], char[] != char[] This would be a problem if the workaround was not so easy. // return true if str1 == str2 template streq(char [] str1, char[] str2) { static if (str1.length!=str2.length) const bool streq=false; else static if (str1[0]!=str2[0]) const bool streq=false; else static if (str1.length==1) const bool streq=true; else const bool streq = .streq!(str1[1..str1.length], str2[1..str2.length]); } --------------------- AESTHETIC: Allow $ as a compile time constant You can always use .length instead, so it's never really a problem. Previously reported as a bug (digitalmars.com digitalmars.D.bugs:5977); could be considered to be a limitation instead.
Jan 17 2006
Don Clugston wrote:The items in this list mostly fall into the category of limitations rather than bugs; but in each case, the limitations are unintuitive. I've listed them in order of decreasing importance. Workarounds are also shown. --------------------- MAJOR: Restrictions on static if in templates Quoting the docs: "StaticIfConditions cannot appear at module scope. They can appear in class, template, struct, union, or function scope. In function scope, the symbols referred to in the AssignExpression can be any that can normally be referenced by an expression at that point. Otherwise, the only symbols that can be referred to are up one scope level from the condition." ... "It does not introduce a new scope even if { } are used for conditionally compiled statements." Together, these restrictions mean that a metafunction can't store intermediate results, so that complex template code like pragma's regex gets quite ugly and convoluted. Workaround: invoke the metafunction every time you want to use the result from it. (Sometimes this can result in a drastic increase in the number of template instantiations required). --------------------- MINOR: Allow concatenation char[] ~ char Desired: const char [] s = "abcdef" ~ 'g'; Workaround: Ugly. Convert char to char[] by taking slices of a string containing all characters. Only works for char, not for wchar, dchar. const char [] s = "abcdef" ~ makechar!('g'); /// converts a single char to a char[] template makechar(int c) { const char [] makechar= x"000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a1b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeef f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"[c..c+1]; } --------------------- AESTHETIC: The . in recursive templates. template fact(int x) { static if (x>1) const int fact = x * .fact!(x-1); else const int fact = 1; } The dot is a workaround, only needed because the constant "fact" we're setting is in scope. Why is it already in the symbol table? The workaround is more complex when the template is not at module scope -- you need to include dot plus fully qualified name. The following example works: struct outer { template fact(int x) { static if (x>1) const int fact = x * .outer.fact!(x-1); else const int fact = 1; } static assert(fact!(6)==8); } If you leave off the dot before the outer, ie static if (x>1) const int fact = x * outer.fact!(x-1); then the error message is: template fact!(x - 1) is not a member of outer which is a little weird. --------------------- MINOR: Allow compile time equality comparisions char[] == char[], char[] != char[] This would be a problem if the workaround was not so easy. // return true if str1 == str2 template streq(char [] str1, char[] str2) { static if (str1.length!=str2.length) const bool streq=false; else static if (str1[0]!=str2[0]) const bool streq=false; else static if (str1.length==1) const bool streq=true; else const bool streq = .streq!(str1[1..str1.length], str2[1..str2.length]); } --------------------- AESTHETIC: Allow $ as a compile time constant You can always use .length instead, so it's never really a problem. Previously reported as a bug (digitalmars.com digitalmars.D.bugs:5977); could be considered to be a limitation instead.This is drastically different from what I've been (all year) talking about. Still, the way Don puts it, I've a hard time figuring out why _not_ do this like he proposes. Of course, the difference (or should I say "_the_ difference" between me and Don is, he's more Politically Correct, more Socially Adept, etc. (No disrespect to Don.)) I tend to pursue issues I feel intuitively deserve the attention, while Don is Diligent (meaning: by the time he suggests something, there is _no_way_ anybody could kick the suggestion in the knee). --- The message (above), to which I'm responding, is written on the 17th, while right now it is the 20th. Considering the respect Don deserves, even a "I've read it, let's see, we'll be back" response would be more appropiate than just silence. ((((( I must be getting in the Meno Pause Age here, but hey, such affected women don't acknowledge that either! ))))))
Jan 19 2006
Georg Wrede wrote:The message (above), to which I'm responding, is written on the 17th, while right now it is the 20th. Considering the respect Don deserves, even a "I've read it, let's see, we'll be back" response would be more appropiate than just silence.I've run into most of the problems Don describes and I agree with all of his suggestions. I hadn't replied until now mostly because I generally avoid "me too" posts, but perhaps it woul help in this case :-) Sean
Jan 20 2006
"Georg Wrede" <georg.wrede nospam.org> wrote in message news:43D05AF5.7030904 nospam.org...The message (above), to which I'm responding, is written on the 17th, while right now it is the 20th. Considering the respect Don deserves, even a "I've read it, let's see, we'll be back" response would be more appropiate than just silence.On the 17th and 18th I attended a conference, and on the 18th I was giving a presentation. So that consumed all my time. On the evening of the 18th, I left for a brief business trip and just got back. So as for what Don's message deserves, the problems have all been corrected and will go out in the next update.
Jan 21 2006
Walter Bright wrote:"Georg Wrede" <georg.wrede nospam.org> wrote in message news:43D05AF5.7030904 nospam.org...Cool!!!The message (above), to which I'm responding, is written on the 17th, while right now it is the 20th. Considering the respect Don deserves, even a "I've read it, let's see, we'll be back" response would be more appropiate than just silence.On the 17th and 18th I attended a conference, and on the 18th I was giving a presentation. So that consumed all my time. On the evening of the 18th, I left for a brief business trip and just got back. So as for what Don's message deserves, the problems have all been corrected and will go out in the next update.
Jan 22 2006
Don Clugston wrote:[everything Don said]signed. most of these seem like relatively minor things but I would personally consider them bugs that should be "fixed". Chris
Jan 20 2006