www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templates lots of newbie qs.

reply "Chris Warwick" <sp m.me.not> writes:
Ok, never used templates before but i think i have the basic idea. Just have 
a few questions and would welcome any corrections / sugestions on way's to 
improve this, my first template.. (surprisingly had very little trouble 
writing this and it compiling, not sure about working tho')

class vector(T)
{

    // fitems will be intialized to default right? So no need for a default 
constructor?

    T[] fitems;

    this(T[] source)
    {
        fitems = source.dup;
    }

    // Am i right in thinking that vector!(int) is a distinct type from T[], 
so how do you pass
    // a template instance of the same time to the constructor? Somthing 
like this???
    // compiles but im not sure if its right..

    this(vector!(T) source)
    {
        fitems = source.fitems.dup;
    }

    void append(T item)
    {
        fitems ~= item;
    }

    bool remove(T item)    // returns true if item removed
    {
        int i = indexOf(item);
        if (i >= 0)
        {
            fitems[i..fitems.length-1] = fitems[i+1..fitems.length];
            fitems.length = fitems.length-1;
            return true;
        }
        else
        {
            return false;
        }
    }

    int indexOf(T item)    // returns -1 if not found
    {
        for (int i = 0; i < fitems.length; i++)
        {
            if (fitems[i] == item) { return i; }
        }
        return -1;
    }

    int length()
    {
        return fitems.length;
    }

    // Do i have the opIndex / opIndexAssign correct?
    // Is there anyway to localy control whether bounds checking is on, so i 
can turn it
    // on or off for just this module?

    T opIndex(int i)
    {
        return fitems[i];
    }

    void opIndexAssign(T item, int index)
    {
        fitems[index] = item;
    }

}

And are class templates value types or referances types?

How well optimized is stuff like this? Will the opIndex/Assign optimize down 
to similar speed as using a basic array?

For basic array stuff like this would it be better to use the "Functions as 
Array Properties" feature? Can that be templatized? Can you writed a generic 
function that takes an array as the first param.. Somthing like this...

template ArrayProps(T)
{
     int indexOf(T[] arr, T item)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (arr[i] == item) { return i; }
        }
        return -1;
    }
}

ArrayPros(int);
int[] foo = [0,1,2,3,4];
int ibetthisdontwork = foo.indexOf(3);

many thanks,

chris 
Mar 08 2007
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Chris Warwick wrote:
 Ok, never used templates before but i think i have the basic idea. Just have 
 a few questions and would welcome any corrections / sugestions on way's to 
 improve this, my first template.. (surprisingly had very little trouble 
 writing this and it compiling, not sure about working tho')
 
 class vector(T)
 {
 
     // fitems will be intialized to default right? So no need for a default 
 constructor?
 
     T[] fitems;

All types in D are initialised to a "sane" default if not given an explicit initialiser. So, yes.
     this(T[] source)
     {
         fitems = source.dup;
     }
 
     // Am i right in thinking that vector!(int) is a distinct type from T[], 
 so how do you pass
     // a template instance of the same time to the constructor? Somthing 
 like this???
     // compiles but im not sure if its right..
 
     this(vector!(T) source)
     {
         fitems = source.fitems.dup;
     }

Yup, that looks good.
     void append(T item)
     {
         fitems ~= item;
     }
 
     bool remove(T item)    // returns true if item removed
     {
         int i = indexOf(item);
         if (i >= 0)
         {
             fitems[i..fitems.length-1] = fitems[i+1..fitems.length];
             fitems.length = fitems.length-1;
             return true;
         }
         else
         {
             return false;
         }
     }
 
     int indexOf(T item)    // returns -1 if not found
     {
         for (int i = 0; i < fitems.length; i++)
         {
             if (fitems[i] == item) { return i; }
         }
         return -1;
     }
 
     int length()
     {
         return fitems.length;
     }
 
     // Do i have the opIndex / opIndexAssign correct?
     // Is there anyway to localy control whether bounds checking is on, so i 
 can turn it
     // on or off for just this module?
 
     T opIndex(int i)
     {
         return fitems[i];
     }
 
     void opIndexAssign(T item, int index)
     {
         fitems[index] = item;
     }

Yup; looks mostly right. You can't locally control bounds-checking. Bounds checking is disabled by throwing the -release compiler switch. Incidentally, you should use size_t for indices; it is an unsigned integer type that spans the address-space.
 }
 
 And are class templates value types or referances types?

They are reference types, just like un-templated classes.
 How well optimized is stuff like this? Will the opIndex/Assign optimize down 
 to similar speed as using a basic array?

Probably not since your opIndex and opIndexAssign are virtual methods; they can be overridden in subclasses, which makes them difficult to inline. Best bet? Write a simple benchmark, compile with -release -inline, and change opIndex/opIndexAssign to "final" methods, if you aren't going to want to override those methods.
 For basic array stuff like this would it be better to use the "Functions as 
 Array Properties" feature? Can that be templatized? Can you writed a generic 
 function that takes an array as the first param.. Somthing like this...
 
 template ArrayProps(T)
 {
      int indexOf(T[] arr, T item)
     {
         for (int i = 0; i < arr.length; i++)
         {
             if (arr[i] == item) { return i; }
         }
         return -1;
     }
 }
 
 ArrayPros(int);

This line above is wrong. It should be: mixin ArrayProps!(int);
 int[] foo = [0,1,2,3,4];
 int ibetthisdontwork = foo.indexOf(3);

Apart from that, it should work fine. Has anyone tried something like this lately: int indexOf(T)(inout T[] arr, T item) { foreach( i, e ; arr ) if( e == item ) return i; return -1; }
 many thanks,
 
 chris 

No problem; hope this helps. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 08 2007
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
news:espao6$q5k$1 digitalmars.com...

Honestly, your post wasn't here when I started posting! 
Mar 08 2007
prev sibling parent reply "Chris Warwick" <sp m.me.not> writes:
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
news:espao6$q5k$1 digitalmars.com...
 }

 And are class templates value types or referances types?

They are reference types, just like un-templated classes.

So they need to be explicitly instantiated... this would be an error.. vector!(int) foo; foo.append(); because foo doesnt reference an actual object yet? Is it the same syntax as creating a normal class... vector!(int) foo = new vector!(int); or with constructor parameters.. vector!(int) foo = new vector!(int)(10); // create a vector with 10 elements. that right?
 Probably not since your opIndex and opIndexAssign are virtual methods;
 they can be overridden in subclasses, which makes them difficult to 
 inline.

Does that mean class templates have inheritance?? That sounds complicated lol.
 ArrayPros(int);

This line above is wrong. It should be: mixin ArrayProps!(int);

*checks online docs* So this creates all stuff inside the ArrayProps template, for type int? And puts them into the local scope, even inside a class or struct definition... I can see that being very useful. :-) thanks cw
Mar 08 2007
parent BCS <BCS pathlink.com> writes:
Chris Warwick wrote:
 Does that mean class templates have inheritance??
 
 That sounds complicated lol.

Just think of it as a class that inherit from a template class and it won't seem complicated.
Mar 08 2007
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Warwick" <sp m.me.not> wrote in message 
news:esp8re$n7g$1 digitalmars.com...
 Ok, never used templates before but i think i have the basic idea. Just 
 have a few questions and would welcome any corrections / sugestions on 
 way's to improve this, my first template.. (surprisingly had very little 
 trouble writing this and it compiling, not sure about working tho')

Okay, here is your code commented with answers (you were mostly right): class vector(T) { T[] fitems; // fitems, being a dynamic array reference, isn't initialized to anything. It's a // zero-length array that points to nothing. If you want it to be a certain length, // you need to make a constructor like the following: this(size_t length) { // Now here, yes, fitems is filled with the default value for T. fitems.length = length; } this(T[] source) { fitems = source.dup; } // Yes, this is entirely right. this(vector!(T) source) { fitems = source.fitems.dup; } void append(T item) { fitems ~= item; } bool remove(T item) // returns true if item removed { int i = indexOf(item); if (i >= 0) { fitems[i..fitems.length-1] = fitems[i+1..fitems.length]; fitems.length = fitems.length-1; return true; } else { return false; } } int indexOf(T item) // returns -1 if not found { for (int i = 0; i < fitems.length; i++) { if (fitems[i] == item) { return i; } } return -1; } int length() { return fitems.length; } // Yes, these are also correct. // Array bounds checking is only disabled in the release build, and // can't be turned on and off per-module unless you compile this module // in release mode and the rest in debug (which is a pain). T opIndex(int i) { return fitems[i]; } void opIndexAssign(T item, int index) { fitems[index] = item; } }
 And are class templates value types or referances types?

They're classes, therefore they're reference types. Templating just changes the types inside the class, not the class itself.
 How well optimized is stuff like this? Will the opIndex/Assign optimize 
 down to similar speed as using a basic array?

If you were to make those short methods (like opIndex and opIndexAssign) "final", and then used the -O -inline flags when compiling, I would imagine they'd be inlined. Class method calls can't be inlined unless the methods are final, since the compiler can then turn a method call of a final method into a static function call. Of course you then can't override the final method if you derive from the class.
 For basic array stuff like this would it be better to use the "Functions 
 as Array Properties" feature? Can that be templatized? Can you writed a 
 generic function that takes an array as the first param.. Somthing like 
 this...

 template ArrayProps(T)
 {
     int indexOf(T[] arr, T item)
    {
        for (int i = 0; i < arr.length; i++)
        {
            if (arr[i] == item) { return i; }
        }
        return -1;
    }
 }

 ArrayPros(int);
 int[] foo = [0,1,2,3,4];
 int ibetthisdontwork = foo.indexOf(3);

Yeah, for simple stuff like this array properties are probably better. You're also pretty close with your code there; you can just write it as a templated function: int indexOf(T)(T[] arr, T item) { for(int i = 0; i < arr.length; i++) { if (arr[i] == item) { return i; } } return -1; } int[] foo = [0,1,2,3,4]; int thisdoeswork = foo.indexOf(3); It's also using IFTI there to determine T implicitly. You might check out the Cashew library (http://www.dsource.org/projects/cashew). It has a bunch of these kinds of array functions in cashew.util.array.
Mar 08 2007
parent reply "Chris Warwick" <sp m.me.not> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:espbiv$s46$1 digitalmars.com...
 Yeah, for simple stuff like this array properties are probably better. 
 You're also pretty close with your code there;  you can just write it as a 
 templated function:

So templated functions dont need to be inside a template block? You only need a template block when you want to group a bunch of stuff together into one template, so the whole lot can be created in one go?
 int indexOf(T)(T[] arr, T item)
 {
    for(int i = 0; i < arr.length; i++)
    {
        if (arr[i] == item) { return i; }
    }
    return -1;
 }

 int[] foo = [0,1,2,3,4];
 int thisdoeswork = foo.indexOf(3);

 It's also using IFTI there to determine T implicitly.

IFTI?
 You might check out the Cashew library 
 (http://www.dsource.org/projects/cashew).  It has a bunch of these kinds 
 of array functions in cashew.util.array.

Looks good, I should be able to learn a lot from that. It's surprised me how very often, even with more advanced features, the D syntax seems to be exactly what you would expect it to be. A very good sign imo, it seems so intuative straight of the bat. thanks, cw
Mar 08 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Warwick" <sp m.me.not> wrote in message 
news:espgo1$16ge$1 digitalmars.com...
 So templated functions dont need to be inside a template block? You only 
 need a template block when you want to group a bunch of stuff together 
 into one template, so the whole lot can be created in one go?

Right. The nice thing about templating functions individually is that then you don't need to specify the template part of the name; instead of typing "templateName!(int).functionName(params)" you just have to type "functionName!(int)(params)", or with IFTI....
 IFTI?

...you can just type "functionName(params)". IFTI stands for "Implicit Function Template Instantiation." When you write a templated function: T func(T)(T val) { return val; } You don't want to have to type out: func!(int)(4); func!(char[])("hi"); So IFTI can implicitly determine what T should be by looking at the parameter list: func(4); // T is determined to be int func("hello"); // T is determined to be char[] It's a very useful feature.
 It's surprised me how very often, even with more advanced features, the D 
 syntax seems to be exactly what you would expect it to be. A very good 
 sign imo, it seems so intuative straight of the bat.

Well, that's why D is the language everyone should be using! :)
Mar 08 2007
parent reply "Chris Warwick" <sp m.me.not> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:espjmc$1d51$1 digitalmars.com...
 "Chris Warwick" <sp m.me.not> wrote in message 
 news:espgo1$16ge$1 digitalmars.com...
 IFTI?

...you can just type "functionName(params)". IFTI stands for "Implicit Function Template Instantiation." When you write a templated function: T func(T)(T val) { return val; } You don't want to have to type out: func!(int)(4); func!(char[])("hi"); So IFTI can implicitly determine what T should be by looking at the parameter list: func(4); // T is determined to be int func("hello"); // T is determined to be char[] It's a very useful feature.

So say you have the following... int indexOf(T)(T[] arr, T item) { // search for and return index } class Foo() { Bar[] fitems; int indexOf(Bar b) { fitems.indexOf(b); // <--- name clash } } How do you get fitems.indexOf to resolve to the templated array property and not the local function of the same name? Obviously it should resolve to the local symbol but i cant figure out how to help teh compiler know i want it to use the template version of indexOf. thanks, cw
Mar 08 2007
next sibling parent "Chris Warwick" <sp m.me.not> writes:
"Chris Warwick" <sp m.me.not> wrote in message 
news:espqa6$1r76$1 digitalmars.com...
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:espjmc$1d51$1 digitalmars.com...
 "Chris Warwick" <sp m.me.not> wrote in message 
 news:espgo1$16ge$1 digitalmars.com...
 IFTI?

...you can just type "functionName(params)". IFTI stands for "Implicit Function Template Instantiation." When you write a templated function: T func(T)(T val) { return val; } You don't want to have to type out: func!(int)(4); func!(char[])("hi"); So IFTI can implicitly determine what T should be by looking at the parameter list: func(4); // T is determined to be int func("hello"); // T is determined to be char[] It's a very useful feature.

So say you have the following... int indexOf(T)(T[] arr, T item) { // search for and return index } class Foo() { Bar[] fitems; int indexOf(Bar b) { fitems.indexOf(b); // <--- name clash

should be: return fitems.indexOf(b);
Mar 08 2007
prev sibling parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Chris Warwick wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:espjmc$1d51$1 digitalmars.com...
 
"Chris Warwick" <sp m.me.not> wrote in message 
news:espgo1$16ge$1 digitalmars.com...

IFTI?

...you can just type "functionName(params)". IFTI stands for "Implicit Function Template Instantiation." When you write a templated function: T func(T)(T val) { return val; } You don't want to have to type out: func!(int)(4); func!(char[])("hi"); So IFTI can implicitly determine what T should be by looking at the parameter list: func(4); // T is determined to be int func("hello"); // T is determined to be char[] It's a very useful feature.

So say you have the following... int indexOf(T)(T[] arr, T item) { // search for and return index } class Foo() { Bar[] fitems; int indexOf(Bar b) { return fitems.indexOf(b); // <--- name clash } } How do you get fitems.indexOf to resolve to the templated array property and not the local function of the same name? Obviously it should resolve to the local symbol but i cant figure out how to help teh compiler know i want it to use the template version of indexOf. thanks, cw

I would expect that to resolve to the global function template, since it is looking for a function whose parameters are (Bar[], Bar). The nested function is not a match for this. If the nested function /was/ a match, I would expect it to call it recursively. To explicitly call the global function, you would have to call it like a regular function and use the unary dot operator: .indexOf(fitems, b); That dot tells it to look at the global scope. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Mar 08 2007
parent reply "Chris Warwick" <sp m.me.not> writes:
"Kirk McDonald" <kirklin.mcdonald gmail.com> wrote in message 
news:esq125$27so$1 digitalmars.com...
 Chris Warwick wrote:
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:espjmc$1d51$1 digitalmars.com...

"Chris Warwick" <sp m.me.not> wrote in message 
news:espgo1$16ge$1 digitalmars.com...

IFTI?

...you can just type "functionName(params)". IFTI stands for "Implicit Function Template Instantiation." When you write a templated function: T func(T)(T val) { return val; } You don't want to have to type out: func!(int)(4); func!(char[])("hi"); So IFTI can implicitly determine what T should be by looking at the parameter list: func(4); // T is determined to be int func("hello"); // T is determined to be char[] It's a very useful feature.

So say you have the following... int indexOf(T)(T[] arr, T item) { // search for and return index } class Foo() { Bar[] fitems; int indexOf(Bar b) { return fitems.indexOf(b); // <--- name clash } } How do you get fitems.indexOf to resolve to the templated array property and not the local function of the same name? Obviously it should resolve to the local symbol but i cant figure out how to help teh compiler know i want it to use the template version of indexOf. thanks, cw

I would expect that to resolve to the global function template, since it is looking for a function whose parameters are (Bar[], Bar). The nested function is not a match for this.

int indexOf(T)(T[] arr, T item) { for(int i = 0; i < arr.length; i++) { if (arr[i] == item) { return i; } } return -1; } class TComponent { TWidget[] fwidgets; int indexOf(TWidget widget) { assert(widget != null); return fwidgets.indexOf(widget); // line 118 } } C:\Documents and Settings\chris\Desktop\dproj>bud Project1.d cjl\component.d(118): function cjl.component.TComponent.indexOf (TWidget) does n ot match parameter types (TWidget[],TWidget) cjl\component.d(118): Error: expected 1 arguments, not 2 cjl\component.d(118): Error: cannot implicitly convert expression (this.fwidgets ) of type TWidget[] to cjl.component.TWidget C:\Documents and Settings\chris\Desktop\dproj>pause Press any key to continue . . . But works fine if I rename the template. Iirc from the docs local scope overrides mixins, so perhaps thats what is happening,
 If the nested function /was/ a match, I would expect it to call it 
 recursively. To explicitly call the global function, you would have to 
 call it like a regular function and use the unary dot operator:

 .indexOf(fitems, b);

 That dot tells it to look at the global scope.

Yeah but the problem is i am using it as an Array Property so it's already got a dot to seperate it from the array. cheers, cw
Mar 08 2007
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Chris Warwick" <sp m.me.not> wrote in message 
news:esq357$2b0j$1 digitalmars.com...
 But works fine if I rename the template. Iirc from the docs local scope 
 overrides mixins, so perhaps thats what is happening,

That's exactly what's happening. Name lookup goes from the inside out, so the compiler finds the class method first, which only takes one parameter, not two.
 Yeah but the problem is i am using it as an Array Property so it's already 
 got a dot to seperate it from the array.

Well keep in mind that fwidgets.indexOf(foo); is just syntactic sugar for: indexOf(fwidgets, foo); When you write a function that takes an array as the first parameter, it does not mean you are extending the array types. It's entirely sugar, and function lookup still happens as normal -- from the local scope up. So all you have to do is rewrite the function call from the property way into the function call way, and use the dot operator to access the globally-scoped symbol.
Mar 08 2007
parent "Chris Warwick" <sp m.me.not> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:esq6gr$2g9p$1 digitalmars.com...
 "Chris Warwick" <sp m.me.not> wrote in message 
 news:esq357$2b0j$1 digitalmars.com...

 is just syntactic sugar for:

 indexOf(fwidgets, foo);

Doh! Forgot i could do that lol. thanks cw
Mar 08 2007
prev sibling parent Don Clugston <dac nospam.com.au> writes:
Chris Warwick wrote:
 It's surprised me how very often, even with more advanced features, the D 
 syntax seems to be exactly what you would expect it to be. A very good sign 
 imo, it seems so intuative straight of the bat.

Exactly. It goes further than that, actually: sometimes things work the exactly the way you'd expect, even if though they're not documented as working <g>.
Mar 08 2007