digitalmars.D - type promotion (on overloaded operators)
- wondermail szm.sk (25/25) Oct 10 2004 Hi there,
- Sjoerd van Leent (54/77) Oct 10 2004 use a bare template to perform bold action. Example:
- Juraj Onderik (43/50) Oct 10 2004 sure I know this :) Ok I meant it little bit different. Can I do "templa...
- Ben Hinkle (54/54) Oct 10 2004 The following should help illustrate my earlier post. It probably
- Ben Hinkle (22/60) Oct 10 2004 You could try something like
Hi there, I've just read the spec - great D, but can I somehow do the "type promotion" e.g. for matrices class CMatrix(T, int M, int N) { T data[M][N]; } CMatrix!(float,3,3) mf; CMatrix!(double,3,3) md; mf + md; // float matrix + double matrix = double matrix // or CMatrix!(float,1,3) v3; CMatrix!(float,3,3) m33; v3 * m33; // and this is really necessary to me ----------- In C++ I did something like this: template <class X, class Y> TAdd {}; template <> TAdd<float,double> { typedef double RET; }; // float + double = double template <class X, class Y, int M, int N> CMatrix<typename TAdd<X,Y>::RET,M,N> operator + (CMatrix<T,M,N> const &a, CMatrix<T,M,N> const &b) { /*...*/ } thanks Juraj Onderik (as I understand templates in D now - it's not really superset of C++ templates, or is it? :) Juraj Onderik
Oct 10 2004
wondermail szm.sk wrote:Hi there, I've just read the spec - great D, but can I somehow do the "type promotion" e.g. for matrices class CMatrix(T, int M, int N) { T data[M][N]; } CMatrix!(float,3,3) mf; CMatrix!(double,3,3) md; mf + md; // float matrix + double matrix = double matrix // or CMatrix!(float,1,3) v3; CMatrix!(float,3,3) m33; v3 * m33; // and this is really necessary to me Juraj Onderikuse a bare template to perform bold action. Example: class Matrix(T, int M, int N) { T data[M][N]; } // bare template template MatrixWorker(Ta, Tb, int Dx, int Dy, To) { Matrix!(To, Dx, Dy) dotProduct( in Matrix!(Ta, Dx, Dy) first, in Matrix!(Tb, Dx, Dy) second) { Matrix!(To, Dx, Dy) result = new Matrix!(To, Dx, Dy); for(uint i; i < Dx; i++) { for(uint j; j < Dy; j++) { result.data[i][j] = cast(To)first.data[i][j] * cast(To)second.data[i][j]; } } return result; } Matrix!(To, Dx, Dy) sum( in Matrix!(Ta, Dx, Dy) first, in Matrix!(Tb, Dx, Dy) second) { Matrix!(To, Dx, Dy) result = new Matrix!(To, Dx, Dy); for(uint i; i < Dx; i++) { for(uint j; j < Dy; j++) { result.data[i][j] = cast(To)first.data[i][j] + cast(To)second.data[i][j]; } } return result; } } int main(char[][] args) { Matrix!(float,3,3) mf = new Matrix!(float,3,3)(/*Matrix init!*/); Matrix!(double,3,3) md = new Matrix!(double,3,3)(/*Matrix init!*/); Matrix!(double,3,3) mo; mo = MatrixWorker!(float, double, 3, 3, double).dotProduct(mf, md); // or mo = MatrixWorker!(float, double, 3, 3, double).sum(mf, md); return 0; } I think this should help. Of course, you can now write specific operators to perform it less painful ;-) But this should give you a kickstart. Regards, Sjoerd N.B. This is D, not MFC, so leave out the C prefix, it's unwanted by the community and especially the big boss.
Oct 10 2004
sure I know this :) Ok I meant it little bit different. Can I do "template function" : C++ : template <class X, class Y> void foo(X x, Y y) {} // general code // specializations - ... foo(1.2,3); foo("one", "two"); // D: template Foo(X,Y) { void foo(X x, Y y) {} } // a,b - some objects , you have specialized Foo for them Foo!(typeof(a),typeof(b)).foo(a,b); // OK foo(a,b); // bad - you must provide "template scope" So the "problem" is that compiler can't deduce template parameters from the function parameters - what c++ actually does. Sure it's not wrong, cause templates in D are new scopes. Anyway, sorry, but I still can't see, how to do it with operators, bacause I cannot parametrize it's argument's: template TM(X, int M, int N) { class Matrix { template NewScope(Y) { void opAdd(TM!(Y,M,N).Matrix m) { /*..*/ } } void opAdd(Matrix m) { /*...*/ } // m is TM!(T,M,N).Matrix } } void main () { TM!(float,3,3).Matrix a; TM!(double,3,3).Matrix b; a.opAdd(b); // this (float,3,3) + (float,3,3) a.NewScope!(double).opAdd(b); // this is NOT + operator }use a bare template to perform bold action. Example: mo = MatrixWorker!(float, double, 3, 3, double).dotProduct(mf, md);dot(a,b) = scalar - not a matrix :) Ok just for fun.I think this should help. Of course, you can now write specific operators to perform it less painful ;-) But this should give you a kickstart. N.B. This is D, not MFC, so leave out the C prefix, it's unwanted by the community and especially the big boss.well I dont use MFC at all, but the C prefix means: class CFoo {} struct SFoo {} enum EFoo {} union UFoo {} but if the BIG boss is against I dont mind :)
Oct 10 2004
The following should help illustrate my earlier post. It probably wouldn't be hard to share more code than I do below but you get the idea. import std.stdio; template GenericVectorOps(Vector,T,int N) { // arithmetic with the same underlying data types Vector opAdd(Vector y) { Vector res; for(int k=0;k<N;k++) { res.data[k] = data[k]+y.data[k]; } return res; } // print out a Vector void print() { foreach(T val; data) writef(val," "); writefln(); } } struct Vector(T,int N) { T[N] data; mixin GenericVectorOps!(Vector,T,N) gops; alias gops.opAdd opAdd; } struct Vector(T:double,int N) { T[N] data; mixin GenericVectorOps!(Vector,T,N) gops; alias gops.opAdd opAdd; // now define mixed type arithmetic with double and float Vector opAdd(.Vector!(float,N) y) { Vector res; for(int k=0;k<N;k++) { res.data[k] = data[k]+y.data[k]; } return res; } } int main() { Vector!(double,3) x; x.data[0] = 1; x.data[1] = 2; x.data[2] = 3; Vector!(float,3) y; y.data[0] = 10; y.data[1] = 20; y.data[2] = 30; Vector!(double,3) z = x+y; Vector!(double,3) w = z+x; x.print(); y.print(); z.print(); w.print(); return 0; }
Oct 10 2004
wondermail szm.sk wrote:Hi there, I've just read the spec - great D, but can I somehow do the "type promotion" e.g. for matrices class CMatrix(T, int M, int N) { T data[M][N]; } CMatrix!(float,3,3) mf; CMatrix!(double,3,3) md; mf + md; // float matrix + double matrix = double matrix // or CMatrix!(float,1,3) v3; CMatrix!(float,3,3) m33; v3 * m33; // and this is really necessary to meYou could try something like template GenericMatrixOps(Matrix,int M, int N) { Matrix opAdd(Matrix y) { // define addition Matrix+Matrix } } class Matrix(T:double, int M, int N) { T[M][N] data; mixin GenericMatrixOps!(Matrix,M,N) genericOps; alias genericOps.opAdd opAdd; // for overloading, maybe Matrix opAdd(Matrix!(float,M,N) y) { // define what to do with double+float matrices } } I haven't actually tried writing something out and compiling it but the general idea is to use mixins to share code and template specialization to define the special cases for mixed type arithmetic.----------- In C++ I did something like this: template <class X, class Y> TAdd {}; template <> TAdd<float,double> { typedef double RET; }; // float + double = double template <class X, class Y, int M, int N> CMatrix<typename TAdd<X,Y>::RET,M,N> operator + (CMatrix<T,M,N> const &a, CMatrix<T,M,N> const &b) { /*...*/ } thanks Juraj Onderik (as I understand templates in D now - it's not really superset of C++ templates, or is it? :) Juraj OnderikD doesn't have implicit template instantiation so using "pure templates" will probably end up being more verbose than in C++. If you use member functions then you don't have to worry about instantiating the templates. -Ben
Oct 10 2004