www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template specialization

reply Derek Parnell <derek nomail.afraid.org> writes:
I've coded ...

 template fill_data(T : int)
 {
    void fill_data(char[] raw_data, out T t)
    {
        t = makeInt( raw_data );
    }
 }

 template fill_data(T : float)
 {
    void fill_data(char[] raw_data, out T t)
    {
        t = toFloat( raw_data );
    }
 }

and later use it like ...


  struct Foo
  {
      float xFloat;
      int   xInt;
  }
  Foo bar;

  fill_data(str, bar.xFloat);
  . . .
  fill_data(str, bar.xInt);

but when compiled I get these errors ...

 test.d(38): template procon2.fill_data(T : int) specialization not allowed
 for deduced parameter T
 test.d(46): template procon2.fill_data(T : float) specialization not
 allowed for deduced parameter T

What is the point of specialization if the compiler can't tell the
difference between data types? I expected that the point of using templates
is to make generic programming simpler.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Justice for David Hicks!"
10/04/2007 6:09:58 PM
Apr 10 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Derek Parnell wrote:
 I've coded ...
 
  template fill_data(T : int)
  {
     void fill_data(char[] raw_data, out T t)
     {
         t = makeInt( raw_data );
     }
  }
 
  template fill_data(T : float)
  {
     void fill_data(char[] raw_data, out T t)
     {
         t = toFloat( raw_data );
     }
  }
 
 and later use it like ...
 
 
   struct Foo
   {
       float xFloat;
       int   xInt;
   }
   Foo bar;
 
   fill_data(str, bar.xFloat);
   . . .
   fill_data(str, bar.xInt);
 
 but when compiled I get these errors ...
 
  test.d(38): template procon2.fill_data(T : int) specialization not allowed
  for deduced parameter T
  test.d(46): template procon2.fill_data(T : float) specialization not
  allowed for deduced parameter T
 
 What is the point of specialization if the compiler can't tell the
 difference between data types? I expected that the point of using templates
 is to make generic programming simpler.
The way I've understood it is that specialization just doesn't work with IFTI. You have to say: fill_data!(float)(str, bar.xFloat); and fill_data!(int)(str, bar.xInt); Consequently, I don't use specialization ever. Use 'static if' checks inside the template if you want to have both IFTI and specialization. It doesn't look as clean for many cases, but at least it's ugly on the library side, rather than the caller side. -bb
Apr 10 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Tue, 10 Apr 2007 19:51:36 +0900, Bill Baxter wrote:

 Derek Parnell wrote:
 What is the point of specialization if the compiler can't tell the
 difference between data types? I expected that the point of using templates
 is to make generic programming simpler.
The way I've understood it is that specialization just doesn't work with IFTI... ... Use 'static if' checks inside the template if you want to have both IFTI and specialization.
Ok, I've tried all the reasonable ways to code this but the magic syntax to do it evades my attempts. This whole area of compile-time capabilities is very poorly documented. Anyway, below is the code I think should work, because it says exactly what I want the compiler to know. Namely, if the type (T) used in the code is and "int" then do the 'int'-stuff, etc ... template fill_data(T) { void fill_data(char[] raw_data, out T t) { static if (T == int) // LINE 42 { t = makeInt( raw_data ); } else static if (T == float) { t = toFloat( raw_data ); } else { fscopy(t, raw_data); } } } but this gives me messages that do not make sense at all to me ... test2.d(42): found ')' when expecting '.' following 'int' test2.d(43): found '{' when expecting identifier following 'int.' test2.d(44): found 't' when expecting ')' test2.d(44): found '=' instead of statement test2.d(46): Declaration expected, not 'else' test2.d(51): Declaration expected, not 'else' test2.d(54): unrecognized declaration Can someone please show me the bleeding obvious correct syntax to use. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 11/04/2007 10:48:18 AM
Apr 10 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Derek Parnell wrote:
 On Tue, 10 Apr 2007 19:51:36 +0900, Bill Baxter wrote:
 
 Derek Parnell wrote:
 What is the point of specialization if the compiler can't tell the
 difference between data types? I expected that the point of using templates
 is to make generic programming simpler.
The way I've understood it is that specialization just doesn't work with IFTI... ... Use 'static if' checks inside the template if you want to have both IFTI and specialization.
Ok, I've tried all the reasonable ways to code this but the magic syntax to do it evades my attempts. This whole area of compile-time capabilities is very poorly documented. Anyway, below is the code I think should work, because it says exactly what I want the compiler to know. Namely, if the type (T) used in the code is and "int" then do the 'int'-stuff, etc ... template fill_data(T) { void fill_data(char[] raw_data, out T t) { static if (T == int) // LINE 42 { t = makeInt( raw_data ); } else static if (T == float) { t = toFloat( raw_data ); } else { fscopy(t, raw_data); } } } but this gives me messages that do not make sense at all to me ... test2.d(42): found ')' when expecting '.' following 'int' test2.d(43): found '{' when expecting identifier following 'int.' test2.d(44): found 't' when expecting ')' test2.d(44): found '=' instead of statement test2.d(46): Declaration expected, not 'else' test2.d(51): Declaration expected, not 'else' test2.d(54): unrecognized declaration Can someone please show me the bleeding obvious correct syntax to use.
You need some is's there like static if (is(T==int))
Apr 10 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Wed, 11 Apr 2007 10:24:20 +0900, Bill Baxter wrote:

 Derek Parnell wrote:
 On Tue, 10 Apr 2007 19:51:36 +0900, Bill Baxter wrote:
 
 Derek Parnell wrote:
 What is the point of specialization if the compiler can't tell the
 difference between data types? I expected that the point of using templates
 is to make generic programming simpler.
The way I've understood it is that specialization just doesn't work with IFTI... ... Use 'static if' checks inside the template if you want to have both IFTI and specialization.
Ok, I've tried all the reasonable ways to code this but the magic syntax to do it evades my attempts. This whole area of compile-time capabilities is very poorly documented. Anyway, below is the code I think should work, because it says exactly what I want the compiler to know. Namely, if the type (T) used in the code is and "int" then do the 'int'-stuff, etc ... template fill_data(T) { void fill_data(char[] raw_data, out T t) { static if (T == int) // LINE 42 { t = makeInt( raw_data ); } else static if (T == float) { t = toFloat( raw_data ); } else { fscopy(t, raw_data); } } } but this gives me messages that do not make sense at all to me ... test2.d(42): found ')' when expecting '.' following 'int' test2.d(43): found '{' when expecting identifier following 'int.' test2.d(44): found 't' when expecting ')' test2.d(44): found '=' instead of statement test2.d(46): Declaration expected, not 'else' test2.d(51): Declaration expected, not 'else' test2.d(54): unrecognized declaration Can someone please show me the bleeding obvious correct syntax to use.
You need some is's there like static if (is(T==int))
Thank you. I ended up with ... template fill_data(T) { void fill_data(char[] raw_data, T* t) { static if (is(T == int) ) { *t = makeInt( raw_data ); } else static if (is(T == float)) { *t = toFloat( raw_data ); } else { fscopy(t, raw_data); } } } Besides your corrected syntax, I had to change the function signature to use pointers rather than use the 'out' modifier as D gets upset when using 'out' with fixed-size arrays. I don't know why it should because doing so makes it yet another exception for writing generic code. Also, I found out that the 'static if' only compiles if it is inside the function declaration - another dumb restriction, IMNHO. Meaning that I couldn't do the obvious thing to avoid using pointers ... template fill_data(T) { static if (is(T == int) ) { void fill_data(char[] raw_data, out T t) { t = makeInt( raw_data ); } else static if (is(T == float)) { void fill_data(char[] raw_data, out T t) { t = toFloat( raw_data ); } } else { void fill_data(char[] raw_data, T t) { fscopy(t, raw_data); } } } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 11/04/2007 12:08:05 PM
Apr 10 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Derek Parnell" <derek nomail.afraid.org> wrote in message 
news:1x1oqnct1uxwh$.1hnmedvjme3hd$.dlg 40tude.net...
 I ended up with ...

 template fill_data(T)
 {
    void fill_data(char[] raw_data, T* t)
    {
        static if (is(T == int) )
        {
            *t = makeInt( raw_data );
        }
        else
        static if (is(T == float))
        {
             *t = toFloat( raw_data );
        }
        else
        {
              fscopy(t, raw_data);
        }
    }
 }

 Besides your corrected syntax, I had to change the function signature to
 use pointers rather than use the 'out' modifier as D gets upset when using
 'out' with fixed-size arrays. I don't know why it should because doing so
 makes it yet another exception for writing generic code.
Don't you hate them? They seem like they'd be so useful, too, if they could be returned and used as out parameters.
 Also, I found out that the 'static if' only compiles if it is inside the
 function declaration - another dumb restriction, IMNHO. Meaning that I
 couldn't do the obvious thing to avoid using pointers ...

 template fill_data(T)
 {
    static if (is(T == int) )
    {
        void fill_data(char[] raw_data, out T t)
        {
            t = makeInt( raw_data );
        }
    else
    static if (is(T == float))
    {
        void fill_data(char[] raw_data, out T t)
        {
             t = toFloat( raw_data );
        }
    }
    else
    {
        void fill_data(char[] raw_data, T t)
        {
              fscopy(t, raw_data);
        }
    }
 }
You're missing a closing brace on that first static if clause. But even still, this is no longer a function template and can then no longer be called using IFTI.
Apr 10 2007
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Tue, 10 Apr 2007 23:07:04 -0400, Jarrett Billingsley wrote:

 ... But even still, this is no longer a function template ...
According to Walter, but I still think it looks like a template that is defining a function <G> -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 11/04/2007 2:13:36 PM
Apr 10 2007
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Derek Parnell" <derek nomail.afraid.org> wrote in message 
news:9vvqf3bppd67.h9vuqy06fl5n.dlg 40tude.net...
 On Tue, 10 Apr 2007 23:07:04 -0400, Jarrett Billingsley wrote:

 ... But even still, this is no longer a function template ...
According to Walter, but I still think it looks like a template that is defining a function <G>
I guess that makes sense. If you get really technical, the static ifs don't introduce a scope, so with any given instantiation of that template, only one symbol, a function, will be declared within it, meaning it's technically a function template.. but I guess evaluation of static ifs doesn't occur until later.
Apr 11 2007