digitalmars.D.learn - Passing a generic struct as parameter
- Zardoz (35/35) Jun 30 2011 I have a parametrized struct (Vector!(T, dim)) that takes two parameters...
- Jonathan M Davis (21/63) Jun 30 2011 The first thing that you need to understand is that Vector is not a type...
- Zardoz (17/85) Jul 01 2011 Thanks. I imagined something similar, that "Vector" alone not is type.
- Simen Kjaeraas (19/53) Jun 30 2011 Private symbols in D are visible outside the defining module (and privat...
- Zardoz (22/93) Jun 30 2011 Well, the problem is that I must do the cast always, see :
- Simen Kjaeraas (11/21) Jul 01 2011 So more likely, this is what you want:
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
Jun 30 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
Jun 30 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:-- Yep, I'm afraid that I have a blog : zardoz.esI 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
Jul 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
Jun 30 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:-- Yep, I'm afraid that I have a blog : zardoz.esI 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.
Jun 30 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
Jul 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:-- Yep, I'm afraid that I have a blog : zardoz.esWell, 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; } }
Jul 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:-- Yep, I'm afraid that I have a blog : zardoz.esOn 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; } }
Jul 01 2011