View mode: basic / threaded / horizontal-split · Log in · Help
September 23, 2012
How to Instantiate struct defined in template
Hello,
I am trying to figure out how templates work and tried to define
the
following template to define vertices of any dimension and
operations
on them.

import std.stdio;
import std.random;
import std.range;
import std.conv;
import std.math;

/*
  * T must be one of the floating point types
  *   float, double, real _ I should be enforcing this.
  */
template  vt(T)
{
   struct vertex {
     this(T[] crds...) {
       if( crds.length < 2 ) {
         throw new.Exception("To small!");
       } else {
	coords.length = crds.length;
	foreach(ref v_coord, in_coord; lockstep(coords, crds))
	{
	  v_coord = in_coord;
	}
       }
     }
     @property T x() { return coords[0];}
     @property T y() { return coords[1];}
     @property T z() { return ( coords.length < 3 ? T.nan :
coords[2] ); }
   }
	
   T euclid_dist(T a, T b) {
     T sum = 0;
     foreach( ref a_crd, ref b_crd; lockstep( a.coords, b.coords )
) {
       sum += (a_crd - b_crd)*(a_crd - b_crd );
     }
     return sqrt(sum);
   }
} //End of template

int main(string argv[] ) {
	vt!(float).vertex v1(0.0,0.0);
	vt!(float).vertex v2(3.0,4.0);
	writefln("The distance between vertex 1 and vertex 2 is ",
		vt!(float).euclid_dist(v1, v2) );
}

When I try to compile this I get the message:

vertex.d(57): Error: found 'v1' when expecting ';' following
statement
vertex.d(58): Error: found 'v2' when expecting ';' following
statement

Lines 57 and 58 are the first two lines in my main() function. I
can't figure out why, from the examples I've looked at I am using
the syntax properly, but am clearly missing something.

Also, since I don't really know what I am doing any criticisms on
how I am defining the vertex template are welcome.

Cheers,

Craig
September 23, 2012
Re: How to Instantiate struct defined in template
On Sunday, September 23, 2012 05:49:06 Craig Dillabaugh wrote:
> Hello,
> I am trying to figure out how templates work and tried to define
> the
> following template to define vertices of any dimension and
> operations
> on them.
> 
> import std.stdio;
> import std.random;
> import std.range;
> import std.conv;
> import std.math;
> 
> /*
>    * T must be one of the floating point types
>    *   float, double, real _ I should be enforcing this.
>    */
> template  vt(T)
> {
>     struct vertex {
>       this(T[] crds...) {
>         if( crds.length < 2 ) {
>           throw new.Exception("To small!");
>         } else {
> 	coords.length = crds.length;
> 	foreach(ref v_coord, in_coord; lockstep(coords, crds))
> 	{
> 	  v_coord = in_coord;
> 	}
>         }
>       }
>       @property T x() { return coords[0];}
>       @property T y() { return coords[1];}
>       @property T z() { return ( coords.length < 3 ? T.nan :
> coords[2] ); }
>     }
> 
>     T euclid_dist(T a, T b) {
>       T sum = 0;
>       foreach( ref a_crd, ref b_crd; lockstep( a.coords, b.coords )
> ) {
>         sum += (a_crd - b_crd)*(a_crd - b_crd );
>       }
>       return sqrt(sum);
>     }
> } //End of template
> 
> int main(string argv[] ) {
> 	vt!(float).vertex v1(0.0,0.0);
> 	vt!(float).vertex v2(3.0,4.0);
> 	writefln("The distance between vertex 1 and vertex 2 is ",
> 		vt!(float).euclid_dist(v1, v2) );
> }
> 
> When I try to compile this I get the message:
> 
> vertex.d(57): Error: found 'v1' when expecting ';' following
> statement
> vertex.d(58): Error: found 'v2' when expecting ';' following
> statement
> 
> Lines 57 and 58 are the first two lines in my main() function. I
> can't figure out why, from the examples I've looked at I am using
> the syntax properly, but am clearly missing something.
> 
> Also, since I don't really know what I am doing any criticisms on
> how I am defining the vertex template are welcome.

Before anything, I'd question why you declared vt at all. If all you're 
putting in it is a single struct, then just templatize the struct directly:

struct Vertex(T)
{
   ...
}

Now, it looks like you have a free function in there as well - euclid_dist - 
but there's no reason to put that in the same template. Just templatize it 
directly. Then you get

T euclid_dist(T)(T a, T b) {...}

And main ends up looking something like

void main()
{
   auto v1 = Vertex!float(0.0, 0.0);
   auto v2 = Vertex!float(2.0, 4.0);
   writefln("The distance between vertex 1 and vertex 2 is %s",
            euclid_dist(v1, v2));
}

It's actually fairly to explicitly declare a template in D outside of 
eponymous templates. If you're dealing with a user-defined type or function, it 
almost always makes more sense to templatize them directly.

Now, as for the exact error message, it's because the syntax that you're using 
to define v1 and v2 is illegal. You'd need to do either

vt!float.vertex v1 = vt!float(0.0, 0.0);

or preferrably.

auto v1 = vt!float(0.0, 0.0);

You can't construct the type on the left-hand side of the assignment operator 
like that.

- Jonathan M Davis
September 23, 2012
Re: How to Instantiate struct defined in template
On Sunday, 23 September 2012 at 04:03:28 UTC, Jonathan M Davis
wrote:
> On Sunday, September 23, 2012 05:49:06 Craig Dillabaugh wrote:
>> Hello,

clip

>
> Before anything, I'd question why you declared vt at all. If 
> all you're
> putting in it is a single struct, then just templatize the 
> struct directly:
>
> struct Vertex(T)
> {
>     ...
> }
>
> Now, it looks like you have a free function in there as well - 
> euclid_dist -
> but there's no reason to put that in the same template. Just 
> templatize it
> directly. Then you get
>
> T euclid_dist(T)(T a, T b) {...}
>
> And main ends up looking something like
>
> void main()
> {
>     auto v1 = Vertex!float(0.0, 0.0);
>     auto v2 = Vertex!float(2.0, 4.0);
>     writefln("The distance between vertex 1 and vertex 2 is %s",
>              euclid_dist(v1, v2));
> }
Thanks. I've switched my code to follow your suggestion. One thing
there was a typo in my euclid_dist function, the code for it, and
main now look like:

T euclid_dist(T)(vertex!T a, vertex!T b) {
	T sum = 0;
	foreach( ref a_crd, ref b_crd; lockstep( a.coords, b.coords ) ) {
		sum += (a_crd - b_crd)*(a_crd - b_crd );
	}
	return sqrt(sum);
}

int main(string argv[] ) {
	auto v1 = vertex!float(0.0,0.0);
	auto v2 = vertex!float(3.0,4.0);
	writeln("The distance between vertex 1 and vertex 2 is ",
		euclid_dist!float(v1, v2) );
	return 0;
}

One question. Is there any way to get the function template to
deduce the type of T from the vertices I pass, so that I can
call:

euclid_dist(v1, v2) )

instead of:

euclid_dist!float(v1, v2) );

>
> It's actually fairly to explicitly declare a template in D 
> outside of
> eponymous templates. If you're dealing with a user-defined type 
> or function, it
> almost always makes more sense to templatize them directly.
>
> Now, as for the exact error message, it's because the syntax 
> that you're using
> to define v1 and v2 is illegal. You'd need to do either
>
> vt!float.vertex v1 = vt!float(0.0, 0.0);
>
> or preferrably.
>
> auto v1 = vt!float(0.0, 0.0);
>
> You can't construct the type on the left-hand side of the 
> assignment operator
> like that.
>
> - Jonathan M Davis

,
September 23, 2012
Re: How to Instantiate struct defined in template
On Sunday, September 23, 2012 06:37:30 Craig Dillabaugh wrote:
> One question. Is there any way to get the function template to
> deduce the type of T from the vertices I pass, so that I can
> call:
> 
> euclid_dist(v1, v2) )
> 
> instead of:
> 
> euclid_dist!float(v1, v2) );

It should infer the types just fine as-is. Templated functions can pretty much 
always infer the template arguments from their function arguments. It's with 
types that that doesn't work (so a constructor requires template arguments, 
but a function does not).

- Jonathan M Davis
September 23, 2012
Re: How to Instantiate struct defined in template
On Sunday, 23 September 2012 at 04:51:31 UTC, Jonathan M Davis
wrote:
> On Sunday, September 23, 2012 06:37:30 Craig Dillabaugh wrote:
>> One question. Is there any way to get the function template to
>> deduce the type of T from the vertices I pass, so that I can
>> call:
>> 
>> euclid_dist(v1, v2) )
>> 
>> instead of:
>> 
>> euclid_dist!float(v1, v2) );
>
> It should infer the types just fine as-is. Templated functions 
> can pretty much
> always infer the template arguments from their function 
> arguments. It's with
> types that that doesn't work (so a constructor requires 
> template arguments,
> but a function does not).
>
> - Jonathan M Davis

Yes, you are right. I thought I had tried it without the !float
and it hadn't worked, but I guess not.

Thanks again for all your help.
Craig
Top | Discussion index | About this forum | D home