Thread overview
[Issue 1661] New: Not possible to specialize on template with integer parameter
Nov 13, 2007
d-bugmail
Nov 13, 2007
d-bugmail
Feb 20, 2008
d-bugmail
Feb 21, 2008
d-bugmail
Feb 21, 2008
d-bugmail
Feb 21, 2008
d-bugmail
Feb 21, 2008
d-bugmail
Feb 29, 2008
d-bugmail
Feb 29, 2008
d-bugmail
Mar 07, 2008
d-bugmail
November 13, 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1661

           Summary: Not possible to specialize on template with integer
                    parameter
           Product: D
           Version: 1.023
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: wbaxter@gmail.com


If you have a template that takes an integer parameter, there appears to be no way to specialize on that integer.

Here are some examples of things that work and things that don't:

/*==========================================================================
 * specialize.d
 *    Written in the D Programming Language (http://www.digitalmars.com/d)
 */
/***************************************************************************
 * Test of specialization in D templates
 *
 * <TODO: Description>
 *
 * Author:  William V. Baxter III
 * Date: 13 Nov 2007
 * License: Public Domain
 */
//===========================================================================

module specialize;
import std.stdio;
import std.string;

struct Container(Scalar,int N)
{
    Scalar[N] values_;
}

template Container2(T) { alias Container!(T,2) Container2; }

struct Simple(T) {
    T[] data;
}

struct Number(int N) {
    const int value = N;
}

void test_specialize(T)() {
    writefln("Not so special: ", typeid(T));
}
void test_specialize(T : float)() {
    writefln("special - float");
}
void test_specialize(T : T[U], U)() {
    writefln("special - Assoc Array of %s -> %s", typeid(U), typeid(T));
}
void test_specialize(T : Container!(T,3))() {
    writefln("Ooh special - CONTAINER T,3");
}
void test_specialize(T : Simple!(T))() {
    writefln("Ooh special - SIMPLE");
}
void test_specialize(T : Number!(2))() {
    writefln("Ooh special - NUMBER = 2");
}

// Cases that don't match

// This doesn't compile
//void test_specialize(T : Number!(int N), int N)() {
//    writefln("Ooh special - NUMBER");
//}
void test_specialize(T : Number!(N), int N)() {
    writefln("Ooh special - NUMBER N");
}
void test_specialize(T : Container2!(T))() {
    writefln("Ooh special - Container2!(T)");
}
void test_specialize(T : Container!(T,N), int N)() {
    writefln("Ooh special - Container!(T,N)");
}


void main() {
    test_specialize!(int)();
    test_specialize!(float)();
    test_specialize!(float[int])();
    test_specialize!(Simple!(int))();
    test_specialize!(Number!(2))();
    test_specialize!(Container!(int,3))();

    // These don't get matched
    test_specialize!(Number!(5))();
    test_specialize!(Container!(int,2))();
    test_specialize!(Container!(int,4))();

}


-- 

November 13, 2007
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #1 from wbaxter@gmail.com  2007-11-13 01:00 -------
Actually this should probably be "no way to specialize *around* the integer parameter".  I.e. fixing the integer in the specialization works (sometimes, except if the integer has been fixed using a template alias like Container2 above).  But what doesn't work is fixing the template and or other template parameters and leaving the number as a parameter.


-- 

February 20, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #2 from bugzilla@digitalmars.com  2008-02-20 17:28 -------
// This doesn't compile
void test_specialize(T : Number!(int N), int N)() {
    writefln("Ooh special - NUMBER");
}

That correctly will not compile because Number!(int N) is invalid syntax.


-- 

February 21, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #3 from wbaxter@gmail.com  2008-02-20 21:31 -------
(In reply to comment #2)
> // This doesn't compile
> void test_specialize(T : Number!(int N), int N)() {
>     writefln("Ooh special - NUMBER");
> }
> 
> That correctly will not compile because Number!(int N) is invalid syntax.
> 

I think that's part of the problem -- there *is* no valid syntax for it.

For a template that takes a type you can specialize using (T:Container!(T)),
but a number is not a type so (T:Container!(T)) doesn't work (at least I'm
guessing that's why it doesn't work).

This doesn't look like it should work either because N hasn't been defined
anywhere.
void test_specialize(T : Number!(N))() {
    writefln("Ooh special - NUMBER N");
}

But it does compile.
I tried the Number!(int N) version just because that looks like a reasonable
syntax for saying "hey we're introducing a new integer parameter named N here".


This affects code that uses templates to implement fixed-size vectors and
operations on them.  It came up when I was trying to implement Vector/Matrix
classes in OpenMesh/D:
http://www.dsource.org/projects/openmeshd/browser/trunk/OpenMeshD/OpenMesh/Core/Geometry/MatrixT.d
http://www.dsource.org/projects/openmeshd/browser/trunk/OpenMeshD/OpenMesh/Core/Geometry/VectorT.d

I don't remember exactly where I ran into it, but if you've got a Vector!(N) it's pretty natural to want to write a template that matches only Vector! but for any N.  If you're writing a template _function_ you can work around it by putting the type as one of the function args.  But it's not always the case (for instance if you want to make a Traits class specialized on Vector!(N).


-- 

February 21, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661


bugzilla@digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |DUPLICATE




------- Comment #4 from bugzilla@digitalmars.com  2008-02-21 01:05 -------
This is exactly the same issue as 1454, but with values instead of types. It's intractable for the same reasons.

*** This bug has been marked as a duplicate of 1454 ***


-- 

February 21, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661


wbaxter@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|DUPLICATE                   |




------- Comment #5 from wbaxter@gmail.com  2008-02-21 02:26 -------
I seem to have been wrong in using function templates.  C++ can't do that either.  I think I must have thought it was simpler to demonstrate with functions when I tried to distill a test case from the original C++ to D.  But it does work with structs in C++, intractible or not.

Working C++ (save to specialize.cpp and compile with "dmc specialize.cpp"):

#include <stdio.h>

template <int N>
struct Number {
    static const int value = N;
};

template <typename T>
struct test_specialize
{
    void talk() { printf("Not so special:\n"); }
};

template<int N>
struct test_specialize<Number<N> >
{
    void talk() { printf("Ooh special - NUMBER N\n"); }
};

int main(int argc, char* argv[])
{
    test_specialize< Number<5> > x;
    x.talk();
    return 0;
}

-----

Not working D:

module specialize;
import std.stdio;

struct Number(int N)
{
    const int value = N;
}

struct test_specialize(T)
{
    void talk() { writefln("Not so special:\n"); }
}

struct test_specialize(T : Number!(N))
{
    void talk() { writefln("Ooh special - NUMBER N\n"); }
}

int main()
{
    test_specialize!(Number!(5)) x;
    x.talk();
    return 0;
}

---

The C++ version outputs "ooh special", and the d version "Not so special".


-- 

February 21, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #6 from bugzilla@digitalmars.com  2008-02-21 14:18 -------
Ok, I agree that that's a bug. I'll fix it.


-- 

February 29, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #7 from wbaxter@gmail.com  2008-02-29 07:59 -------
Am I right in thinking this is the actual syntax that should work?:

struct test_specialize(T : Number!(N), int N)
{
    void talk() { writefln("Ooh special - NUMBER N\n"); }
}
test_specialize!(Number!(5)) x;


That's a minor variation on an example in the docs:

  template Foo(T: T[U], U)
  {
      ...
  }
  Foo!(int[long]) // instantiates Foo with T set to int, U set to long


(But the int-arg version still doesn't work, I'm just checking that the above
is what *should* work.)


-- 

February 29, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661





------- Comment #8 from onlystupidspamhere@yahoo.se  2008-02-29 14:07 -------
(In reply to comment #7)
> Am I right in thinking this is the actual syntax that should work?:
> 
> struct test_specialize(T : Number!(N), int N)
> {
>     void talk() { writefln("Ooh special - NUMBER N\n"); }
> }
> test_specialize!(Number!(5)) x;

I would expect it to be. But this issue isn't limited to int parameters. Other primitive types don't work either. Also, more complex pattern matching fails:

  struct a(S, T) {}
  struct b(T : a!(N, a!(N, int)), N) {}
  alias a!(float,int) A;
  alias a!(float, A) B;
  b!(B, float) x; // fails, and so does b!(B) x;

foo.d:5: template instance b!(a!(float,a!(float,int) ) ,float) does not match
any template declaration
foo.d:5: Error: b!(a!(float,a!(float,int) ) ,float) is used as a type
foo.d:5: variable foo.x voids have no value

This is a bit problematic for someone creating a new compiler for D since it's not really clear how complex types the language should be able to match. The specification only mentions (http://www.digitalmars.com/d/1.0/template.html) that they should be types. But that's a bit confusing since Number!(N) isn't a valid type. You can't e.g. alias it, there's no parametrized alias syntax:

  alias IntNPair N = tuple!(int, N);

One could instantiate the code above with Number(float) or Number!(float), and
get tuple!(int, float).


-- 

March 07, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1661


bugzilla@digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |FIXED




------- Comment #9 from bugzilla@digitalmars.com  2008-03-07 00:22 -------
Fixed dmd 1.028 and 2.012


--