Thread overview
Passing a generic struct as parameter
Jun 30, 2011
Zardoz
Jul 01, 2011
Jonathan M Davis
Jul 01, 2011
Zardoz
Jul 01, 2011
Simen Kjaeraas
Jul 01, 2011
Zardoz
Jul 01, 2011
Simen Kjaeraas
Jul 01, 2011
Zardoz
Jul 01, 2011
Zardoz
June 30, 2011
I have a parametrized struct (Vector!(T, dim)) that takes two parameters (Type and a number). And made some Alias with defaults parameters.

In other struct (Matrix!(T, dim)), that uses these struct to represent a matrix in column-major order. I have a internall alias for Vector using internally (alias Vector!(T,dim_) VCol;) . The problem that I have it's when I try to use opIndexAssign to assign to a column a Vector. I try this :

void opIndexAssign(Vector v, size_t j) {
	if ( code that see if VCol if same type that v ) {
		col[j] = v;
	} else {
		col[j] = cast (VCol) v;
	}
}

But not compile... I get this error :
Error: struct zmath.vector.Vector(T,ulong dim_) if (__traits
(isFloating,T)) is used as a type
Error: template instance zmath.matrix.Matrix!(float,2) error instantiating

So finally I try this :
/**
* Assigns a new column vector
*/
void opIndexAssign(VCol v, size_t j) {
	col[j] = v;
}

But now I must do cast outside, even knowing that are same type. Plus now I must keep VCol alias public.

How should fix this, or What is the correct way of doing this ?


Note : I have a opCast for Vector that cast between Vectors with different parameters and it's checked that works.

Second Question : I'm thinking publish this small Vector/Quaternion/ Matrix lib that I made learning D2.. where I should put and how ? (and I use Git)

-- 
Yep, I'm afraid that I have a blog : zardoz.es
July 01, 2011
On 2011-06-30 16:39, Zardoz wrote:
> I have a parametrized struct (Vector!(T, dim)) that takes two parameters
> (Type and a number). And made some Alias with defaults parameters.
> 
> In other struct (Matrix!(T, dim)), that uses these struct to represent a
> matrix in column-major order. I have a internall alias for Vector using
> internally (alias Vector!(T,dim_) VCol;) . The problem that I have it's
> when I try to use opIndexAssign to assign to a column a Vector. I try
> this :
> 
> void opIndexAssign(Vector v, size_t j) {
> if ( code that see if VCol if same type that v ) {
> col[j] = v;
> } else {
> col[j] = cast (VCol) v;
> }
> }
> 
> But not compile... I get this error :
> Error: struct zmath.vector.Vector(T,ulong dim_) if (__traits
> (isFloating,T)) is used as a type
> Error: template instance zmath.matrix.Matrix!(float,2) error instantiating
> 
> So finally I try this :
> /**
> * Assigns a new column vector
> */
> void opIndexAssign(VCol v, size_t j) {
> col[j] = v;
> }
> 
> But now I must do cast outside, even knowing that are same type. Plus now I must keep VCol alias public.
> 
> How should fix this, or What is the correct way of doing this ?
> 
> 
> Note : I have a opCast for Vector that cast between Vectors with different parameters and it's checked that works.
> 
> Second Question : I'm thinking publish this small Vector/Quaternion/ Matrix lib that I made learning D2.. where I should put and how ? (and I use Git)

The first thing that you need to understand is that Vector is not a type. It does not exist. Vector!(int, 4) is a type. Vector!(float, 3) is a type. Vector is not. Vector is a template for a type. When you use a template, you instantiate it for a particular set of arguments, and that creates a new type. An instantiation of a templated type such as Vector is a type, and every instantiation is its own, separate type which has no connection with any other instantion of that template. So, it makes no sense for a function to take a Vector (though within the Vector template that works, because Vector stands for that particular instantiation inside of the Vector template). If you want a function to take multiple instantiations of a template, then you need to templatize the function. If you want it to take a particular instantiation of a template, then you give its parameter that exact template instantiation.

Now, if you want two separate instantions (such as Vector!(int, 3) and Vector!
(float, 3)) to interact, you're going to need to either write opCasts to cast
between them or have templated functions which are templated on both of their
types (e.g. func(V1, V2)(V1 vector1, V2 vector2) {...}). They are two
completed different types, just like if you created IntVector and FloatVector,
so you have to write code which allows them to interact. They aren't going to
just work together because they came from the same template.

- Jonathan M Davis
July 01, 2011
On Fri, 01 Jul 2011 01:39:53 +0200, Zardoz <luis.panadero@gmail.com> wrote:

> I have a parametrized struct (Vector!(T, dim)) that takes two parameters
> (Type and a number). And made some Alias with defaults parameters.
>
> In other struct (Matrix!(T, dim)), that uses these struct to represent a
> matrix in column-major order. I have a internall alias for Vector using
> internally (alias Vector!(T,dim_) VCol;) . The problem that I have it's
> when I try to use opIndexAssign to assign to a column a Vector. I try
> this :
>
> void opIndexAssign(Vector v, size_t j) {
> 	if ( code that see if VCol if same type that v ) {
> 		col[j] = v;
> 	} else {
> 		col[j] = cast (VCol) v;
> 	}
> }
>
> But not compile... I get this error :
> Error: struct zmath.vector.Vector(T,ulong dim_) if (__traits
> (isFloating,T)) is used as a type
> Error: template instance zmath.matrix.Matrix!(float,2) error instantiating
>
> So finally I try this :
> /**
> * Assigns a new column vector
> */
> void opIndexAssign(VCol v, size_t j) {
> 	col[j] = v;
> }
>
> But now I must do cast outside, even knowing that are same type. Plus now
> I must keep VCol alias public.
>
> How should fix this, or What is the correct way of doing this ?

Private symbols in D are visible outside the defining module (and private
symbols are accessible inside the same module), so having the alias private
is no problem.

In other words, the latter solution is good, and should not require any
casting or public alias.

Or have I perhaps misunderstood? Is there some other reason you need to
cast?


Also, the error message you get (Vector(...) is used as a type) is
indicative of your referring to the Vector template rather than an
instantiation. Struct templates in D behave as if defined thusly:

template Foo( T ) {
    struct Foo {
    }
}

for a struct Foo( T ).


> Note : I have a opCast for Vector that cast between Vectors with
> different parameters and it's checked that works.
>
> Second Question : I'm thinking publish this small Vector/Quaternion/
> Matrix lib that I made learning D2.. where I should put and how ? (and I
> use Git)

GitHub, then? Or dsource.org.

-- 
  Simen
July 01, 2011
Well, the problem is that I must do the cast always, see :

// alias Matrix!(real,4) Mat4r;
// alias Vector!(float, 3) Vec3f;
// alias Vector!(real, 4) Vec4r;
// In Mat4r, VCol it's aliased to Vector!(real, 4)

auto tcol = Mat4r.IDENTITY;

auto v = cast(tcol.VCol) Vec3f(1, 2 ,3 ); auto v2 = Vec4r(-1, -2 ,-3 ,-4);

tcol[1] = v2; // Do a compiler error
tcol[2] = v;

I get this error :
Error: function zmath.matrix.Matrix!(real,4).Matrix.opIndexAssign (real
c, ulong row, ulong cl) is not callable using argument types (Vector!
(real,4),int)
Error: cannot implicitly convert expression (v2) of type Vector!(real,4)
to Vector!(real,dim)

If I do cast(tcol.Vcol) to v2, this works.
Plus if I do a typeid(v1), typeid(v2) to see his types, I get this :
zmath.vector.Vector!(real,4).Vector  zmath.vector.Vector!(real,dim).Vector

On Fri, 01 Jul 2011 02:29:58 +0200, Simen Kjaeraas wrote:
> On Fri, 01 Jul 2011 01:39:53 +0200, Zardoz <luis.panadero@gmail.com> wrote:
> 
>> I have a parametrized struct (Vector!(T, dim)) that takes two
>> parameters (Type and a number). And made some Alias with defaults
>> parameters.
>>
>> In other struct (Matrix!(T, dim)), that uses these struct to represent
>> a matrix in column-major order. I have a internall alias for Vector
>> using internally (alias Vector!(T,dim_) VCol;) . The problem that I
>> have it's when I try to use opIndexAssign to assign to a column a
>> Vector. I try this :
>>
>> void opIndexAssign(Vector v, size_t j) {
>> 	if ( code that see if VCol if same type that v ) {
>> 		col[j] = v;
>> 	} else {
>> 		col[j] = cast (VCol) v;
>> 	}
>> }
>>
>> But not compile... I get this error : Error: struct
>> zmath.vector.Vector(T,ulong dim_) if (__traits (isFloating,T)) is used
>> as a type
>> Error: template instance zmath.matrix.Matrix!(float,2) error
>> instantiating
>>
>> So finally I try this :
>> /**
>> * Assigns a new column vector
>> */
>> void opIndexAssign(VCol v, size_t j) {
>> 	col[j] = v;
>> }
>>
>> But now I must do cast outside, even knowing that are same type. Plus now I must keep VCol alias public.
>>
>> How should fix this, or What is the correct way of doing this ?
> 
> Private symbols in D are visible outside the defining module (and private symbols are accessible inside the same module), so having the alias private is no problem.
> 
> In other words, the latter solution is good, and should not require any casting or public alias.
> 
> Or have I perhaps misunderstood? Is there some other reason you need to cast?
> 
> 
> Also, the error message you get (Vector(...) is used as a type) is
> indicative of your referring to the Vector template rather than an
> instantiation. Struct templates in D behave as if defined thusly:
> 
> template Foo( T ) {
>      struct Foo {
>      }
> }
> 
> for a struct Foo( T ).
> 
> 
>> Note : I have a opCast for Vector that cast between Vectors with different parameters and it's checked that works.
>>
>> Second Question : I'm thinking publish this small Vector/Quaternion/ Matrix lib that I made learning D2.. where I should put and how ? (and I use Git)
> 
> GitHub, then? Or dsource.org.





-- 
Yep, I'm afraid that I have a blog : zardoz.es
July 01, 2011
Thanks. I imagined something similar, that "Vector" alone not is type. How I can templatize opIndexAssign function ? I tried this :

void opIndexAssign(U)(U v, size_t j) {
  col[j] = v;
}

And I get a error : Error: template zmath.matrix.Matrix!(float,2).Matrix.opIndexAssign(U) conflicts with function zmath.matrix.Matrix!(float,2).Matrix.opIndexAssign at src/matrix.d(261)

That I interpret that this opIndexAssign clash with other opIndexAssign that I have to direct access to
matrix  cells
void opIndexAssign(T c, size_t row, size_t cl) {
	col[cl][row] = c;
}

I said before that I made a opCast for Vector ?

On Fri, 01 Jul 2011 00:12:43 +0000, Jonathan M Davis wrote:

> On 2011-06-30 16:39, Zardoz wrote:
>> I have a parametrized struct (Vector!(T, dim)) that takes two
>> parameters (Type and a number). And made some Alias with defaults
>> parameters.
>> 
>> In other struct (Matrix!(T, dim)), that uses these struct to represent
>> a matrix in column-major order. I have a internall alias for Vector
>> using internally (alias Vector!(T,dim_) VCol;) . The problem that I
>> have it's when I try to use opIndexAssign to assign to a column a
>> Vector. I try this :
>> 
>> void opIndexAssign(Vector v, size_t j) { if ( code that see if VCol if
>> same type that v ) { col[j] = v;
>> } else {
>> col[j] = cast (VCol) v;
>> }
>> }
>> 
>> But not compile... I get this error : Error: struct
>> zmath.vector.Vector(T,ulong dim_) if (__traits (isFloating,T)) is used
>> as a type
>> Error: template instance zmath.matrix.Matrix!(float,2) error
>> instantiating
>> 
>> So finally I try this :
>> /**
>> * Assigns a new column vector
>> */
>> void opIndexAssign(VCol v, size_t j) { col[j] = v;
>> }
>> 
>> But now I must do cast outside, even knowing that are same type. Plus now I must keep VCol alias public.
>> 
>> How should fix this, or What is the correct way of doing this ?
>> 
>> 
>> Note : I have a opCast for Vector that cast between Vectors with different parameters and it's checked that works.
>> 
>> Second Question : I'm thinking publish this small Vector/Quaternion/ Matrix lib that I made learning D2.. where I should put and how ? (and I use Git)
> 
> The first thing that you need to understand is that Vector is not a type. It does not exist. Vector!(int, 4) is a type. Vector!(float, 3) is a type. Vector is not. Vector is a template for a type. When you use a template, you instantiate it for a particular set of arguments, and that creates a new type. An instantiation of a templated type such as Vector is a type, and every instantiation is its own, separate type which has no connection with any other instantion of that template. So, it makes no sense for a function to take a Vector (though within the Vector template that works, because Vector stands for that particular instantiation inside of the Vector template). If you want a function to take multiple instantiations of a template, then you need to templatize the function. If you want it to take a particular instantiation of a template, then you give its parameter that exact template instantiation.
> 
> Now, if you want two separate instantions (such as Vector!(int, 3) and
> Vector! (float, 3)) to interact, you're going to need to either write
> opCasts to cast between them or have templated functions which are
> templated on both of their types (e.g. func(V1, V2)(V1 vector1, V2
> vector2) {...}). They are two completed different types, just like if
> you created IntVector and FloatVector, so you have to write code which
> allows them to interact. They aren't going to just work together because
> they came from the same template.
> 
> - Jonathan M Davis





-- 
Yep, I'm afraid that I have a blog : zardoz.es
July 01, 2011
On Fri, 01 Jul 2011 08:58:32 +0200, Zardoz <luis.panadero@gmail.com> wrote:

> Well, the problem is that I must do the cast always, see :
>
> // alias Matrix!(real,4) Mat4r;
> // alias Vector!(float, 3) Vec3f;
> // alias Vector!(real, 4) Vec4r;
> // In Mat4r, VCol it's aliased to Vector!(real, 4)
>
> auto tcol = Mat4r.IDENTITY;
>
> auto v = cast(tcol.VCol) Vec3f(1, 2 ,3 );
> auto v2 = Vec4r(-1, -2 ,-3 ,-4);
>
> tcol[1] = v2; // Do a compiler error
> tcol[2] = v;

So more likely, this is what you want:

void opIndexAssign(U)(Vector!(U,dim) v, size_t j) {
    static if (is(U == T)) {
        col[j] = v;
    } else {
        col[j] = cast(VCol)v;
    }
}


-- 
  Simen
July 01, 2011
Finally I try this small test code :

struct A(T, int U) {
	T x;
	static enum foo = U;

	Tout opCast( Tout ) ()
	if (isA!Tout)	{
		Tout nt;
		nt.x = x;
		return nt;
	}

	string toString() {
		return to!string(x);
	}
}

struct B(T, int I) {
	enum foo2 = I;

	alias A!(T, foo2) Internal;

	Internal[foo2 * 2] y;

	void opIndexAssign(K) (K v, size_t j)
	if (isA!(K) && K.foo == Internal.foo && is(typeof(K.x) == typeof(y[0].x)) ) {
		y[j] = v;
	}

	void opIndexAssign(K) (K v, size_t j)
	if (isA!(K) && (K.foo != Internal.foo || !is(typeof(K.x) == typeof(y[0].x))) ) {
		y[j] = Internal(v.x);
	}

}

template isA(T) {
  immutable bool isA = __traits(compiles,
        (){
            T t;
            auto x = t.x;
            auto u = t.foo;
        }
    );
}


auto bla = A!(int, 2) (10);
auto bla2 =A!(int, 5) (5)

B!(int, 3) bleh;

bleh[1] = bla;
bleh[3] = bla2;

writeln(bleh.y);

And write : [0, 10, 0, 5, 0, 0]

So this works. Only I need to discover why when I try it over Vector and Matrix class, I get errors...

Finally, I upload to github : git://github.com/Zardoz89/zmath.git
I hope that I not write some barbaric thing in my code....
I do all self-learning D

On Fri, 01 Jul 2011 17:19:36 +0200, Simen Kjaeraas wrote:

> On Fri, 01 Jul 2011 08:58:32 +0200, Zardoz <luis.panadero@gmail.com> wrote:
> 
>> Well, the problem is that I must do the cast always, see :
>>
>> // alias Matrix!(real,4) Mat4r;
>> // alias Vector!(float, 3) Vec3f;
>> // alias Vector!(real, 4) Vec4r;
>> // In Mat4r, VCol it's aliased to Vector!(real, 4)
>>
>> auto tcol = Mat4r.IDENTITY;
>>
>> auto v = cast(tcol.VCol) Vec3f(1, 2 ,3 ); auto v2 = Vec4r(-1, -2 ,-3
>> ,-4);
>>
>> tcol[1] = v2; // Do a compiler error
>> tcol[2] = v;
> 
> So more likely, this is what you want:
> 
> void opIndexAssign(U)(Vector!(U,dim) v, size_t j) {
>      static if (is(U == T)) {
>          col[j] = v;
>      } else {
>          col[j] = cast(VCol)v;
>      }
> }





-- 
Yep, I'm afraid that I have a blog : zardoz.es
July 01, 2011
Ok, I fixed it. I just need to put (K) type parameter to the other opIndexAssign

D not allow overload operators/methods with different type parameters. They must share same type parameters :

void opIndexAssign(K)(K c, size_t row, size_t cl) {... }

void opIndexAssign(K) (K v, size_t j) { ... }

On Fri, 01 Jul 2011 21:46:56 +0000, Zardoz wrote:

> Finally I try this small test code :
> 
> struct A(T, int U) {
> 	T x;
> 	static enum foo = U;
> 
> 	Tout opCast( Tout ) ()
> 	if (isA!Tout)	{
> 		Tout nt;
> 		nt.x = x;
> 		return nt;
> 	}
> 
> 	string toString() {
> 		return to!string(x);
> 	}
> }
> 
> struct B(T, int I) {
> 	enum foo2 = I;
> 
> 	alias A!(T, foo2) Internal;
> 
> 	Internal[foo2 * 2] y;
> 
> 	void opIndexAssign(K) (K v, size_t j) if (isA!(K) && K.foo ==
> 	Internal.foo && is(typeof(K.x) == typeof(y[0].x)) ) {
> 		y[j] = v;
> 	}
> 
> 	void opIndexAssign(K) (K v, size_t j) if (isA!(K) && (K.foo !=
> 	Internal.foo || !is(typeof(K.x) == typeof(y[0].x))) ) {
> 		y[j] = Internal(v.x);
> 	}
> 
> }
> 
> template isA(T) {
>   immutable bool isA = __traits(compiles,
>         (){
>             T t;
>             auto x = t.x;
>             auto u = t.foo;
>         }
>     );
> }
> 
> 
> auto bla = A!(int, 2) (10);
> auto bla2 =A!(int, 5) (5)
> 
> B!(int, 3) bleh;
> 
> bleh[1] = bla;
> bleh[3] = bla2;
> 
> writeln(bleh.y);
> 
> And write : [0, 10, 0, 5, 0, 0]
> 
> So this works. Only I need to discover why when I try it over Vector and Matrix class, I get errors...
> 
> Finally, I upload to github : git://github.com/Zardoz89/zmath.git I hope that I not write some barbaric thing in my code.... I do all self-learning D
> 
> On Fri, 01 Jul 2011 17:19:36 +0200, Simen Kjaeraas wrote:
> 
>> On Fri, 01 Jul 2011 08:58:32 +0200, Zardoz <luis.panadero@gmail.com> wrote:
>> 
>>> Well, the problem is that I must do the cast always, see :
>>>
>>> // alias Matrix!(real,4) Mat4r;
>>> // alias Vector!(float, 3) Vec3f;
>>> // alias Vector!(real, 4) Vec4r;
>>> // In Mat4r, VCol it's aliased to Vector!(real, 4)
>>>
>>> auto tcol = Mat4r.IDENTITY;
>>>
>>> auto v = cast(tcol.VCol) Vec3f(1, 2 ,3 ); auto v2 = Vec4r(-1, -2 ,-3
>>> ,-4);
>>>
>>> tcol[1] = v2; // Do a compiler error
>>> tcol[2] = v;
>> 
>> So more likely, this is what you want:
>> 
>> void opIndexAssign(U)(Vector!(U,dim) v, size_t j) {
>>      static if (is(U == T)) {
>>          col[j] = v;
>>      } else {
>>          col[j] = cast(VCol)v;
>>      }
>> }





-- 
Yep, I'm afraid that I have a blog : zardoz.es