Jump to page: 1 2
Thread overview
Templates lots of newbie qs.
Mar 08, 2007
Chris Warwick
Mar 08, 2007
Daniel Keep
Mar 08, 2007
Chris Warwick
Mar 08, 2007
BCS
Mar 08, 2007
Chris Warwick
Mar 08, 2007
Chris Warwick
Mar 08, 2007
Chris Warwick
Mar 08, 2007
Kirk McDonald
Mar 08, 2007
Chris Warwick
Mar 09, 2007
Chris Warwick
Mar 08, 2007
Don Clugston
March 08, 2007
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


March 08, 2007
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/
March 08, 2007
"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.


March 08, 2007
"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!


March 08, 2007
"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


March 08, 2007
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.
March 08, 2007
"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


March 08, 2007
"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!  :)


March 08, 2007
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>.
March 08, 2007
"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


« First   ‹ Prev
1 2