Thread overview
Template metaprogramming quirk list
Jan 17, 2006
Don Clugston
Jan 20, 2006
Georg Wrede
Jan 20, 2006
Sean Kelly
Jan 22, 2006
Walter Bright
Jan 22, 2006
Georg Wrede
Jan 20, 2006
Chris Lajoie
January 17, 2006
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.
January 20, 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! ))))))
January 20, 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
January 20, 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
January 22, 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.


January 22, 2006
Walter Bright wrote:
> "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. 

Cool!!!