digitalmars.D.learn - static if and templates
- Oliver (24/24) Sep 27 2007 Hi,
- Christian Kamm (23/34) Sep 27 2007 Static if requires the condition to be evaluated at compile time, but ex...
- Oliver (5/33) Sep 27 2007 what i do not understand is the following: if expr is a runtime construc...
- Christian Kamm (32/38) Sep 27 2007 Well, I'm pretty sure expr.mangleof becomes typeof(expr).mangleof, so
- Don Clugston (4/33) Sep 27 2007 If you use:
- Christian Kamm (7/17) Sep 27 2007 Indeed that will accept anything that provides opIndex. You can check fo...
- Oliver (35/35) Sep 28 2007 Christian and Don,
Hi, in the function isMatrix I would like to access the function isArray. Unfortunately, this does not work, even though if I use the definition of isArray directly it does work. How could I write the code using isArray? Thanks for any hints. Oliver ------------------ import std.stdio; bool isArray(T)(T expr){ return (expr.mangleof)[0] == 'A'; } bool isMatrix(T)(T expr){ static if ( (expr.mangleof)[0] == 'A' ) // works //static if ( isArray(expr) ) // does NOT work return (expr.mangleof)[1] == 'A'; else return false; } void main () { double s = 1.; double[] v = [1.,2.]; double[][] m = [[1.,2.]]; writefln("s: ", isArray(s), " ", isMatrix(s) ); writefln("v: ", isArray(v), " ", isMatrix(v) ); writefln("m: ", isArray(m), " ", isMatrix(m) ); }
Sep 27 2007
Oliver wrote:bool isArray(T)(T expr){ return (expr.mangleof)[0] == 'A'; } bool isMatrix(T)(T expr){ static if ( (expr.mangleof)[0] == 'A' ) // works //static if ( isArray(expr) ) // does NOT work return (expr.mangleof)[1] == 'A'; else return false; }Static if requires the condition to be evaluated at compile time, but expr is a run time construct. You can make these two compile-time evaluateable by switching to templates: --- import std.stdio; template isArray(T){ const isArray = (T.mangleof)[0] == 'A'; } template isMatrix(T){ static if ( isArray!(T) ) const isMatrix = (T.mangleof)[1] == 'A'; else const isMatrix = false; } void main () { double s = 1.; double[] v = [1.,2.]; double[][] m = [[1.,2.]]; writefln("s: ", isArray!(typeof(s)), " ", isMatrix!(typeof(s)) ); writefln("v: ", isArray!(typeof(v)), " ", isMatrix!(typeof(v)) ); writefln("m: ", isArray!(typeof(m)), " ", isMatrix!(typeof(m)) ); }
Sep 27 2007
Christian, thank you for your reply and your code.Static if requires the condition to be evaluated at compile time, but expr is a run time construct. You can make these two compile-time evaluateable by switching to templates:what i do not understand is the following: if expr is a runtime construct, how come expr.mangleof works? for this to work (in my beginner thinking) the compiler takes, say m, from main and inserts it into expr.mangleof. Now, why is it not possible for the compile to insert the expr into isArray? I think there is some fundamental thing i don't understand. Any wisdom you can share? Oliver--- import std.stdio; template isArray(T){ const isArray = (T.mangleof)[0] == 'A'; } template isMatrix(T){ static if ( isArray!(T) ) const isMatrix = (T.mangleof)[1] == 'A'; else const isMatrix = false; } void main () { double s = 1.; double[] v = [1.,2.]; double[][] m = [[1.,2.]]; writefln("s: ", isArray!(typeof(s)), " ", isMatrix!(typeof(s)) ); writefln("v: ", isArray!(typeof(v)), " ", isMatrix!(typeof(v)) ); writefln("m: ", isArray!(typeof(m)), " ", isMatrix!(typeof(m)) ); }
Sep 27 2007
what i do not understand is the following: if expr is a runtime construct, how come expr.mangleof works? for this to work (in my beginner thinking) the compiler takes, say m, from main and inserts it into expr.mangleof. Now, why is it not possible for the compile to insert the expr into isArray? I think there is some fundamental thing i don't understand. Any wisdom you can share?Well, I'm pretty sure expr.mangleof becomes typeof(expr).mangleof, so --- class A {} class B : A {} A a = new B; writefln(a.mangleof); --- Would give you the mangled name of A (compile time type) and not of B. By the way, a more conventional way of writing your isArray and isMatrix functions would be --- template isArray(T){ static if(is(T U : U[])) const isArray = true; else const isArray = false; } template isMatrix(T){ static if(is(T U : U[][])) const isMatrix = true; else const isMatrix = false; } --- And finally, I don't recommend using T[][] as a matrix type: it's literally an array of arrays, so each row mat[i] does not even need to have the same length and you won't get very good performance. So, unless that's what you want, I recommend looking through the projects at dsource for implementations of vectors and matrices - I think there are several. Cheers, Christian
Sep 27 2007
Christian Kamm wrote:If you use: static if (is(typeof(T[0])) it will work for user-defined types.what i do not understand is the following: if expr is a runtime construct, how come expr.mangleof works? for this to work (in my beginner thinking) the compiler takes, say m, from main and inserts it into expr.mangleof. Now, why is it not possible for the compile to insert the expr into isArray? I think there is some fundamental thing i don't understand. Any wisdom you can share?Well, I'm pretty sure expr.mangleof becomes typeof(expr).mangleof, so --- class A {} class B : A {} A a = new B; writefln(a.mangleof); --- Would give you the mangled name of A (compile time type) and not of B. By the way, a more conventional way of writing your isArray and isMatrix functions would be --- template isArray(T){ static if(is(T U : U[])) const isArray = true; else const isArray = false; }
Sep 27 2007
Don Clugston wrote:Indeed that will accept anything that provides opIndex. You can check for opSlice and the rest in a similar way, if your code requires them to be available. With these checks, you can even skip the static if: template hasIndexAndSlice(T) { const bool hasIndexAndSlice = is(typeof(T[0])) && is(typeof(T[0..0])); }template isArray(T){ static if(is(T U : U[])) const isArray = true; else const isArray = false; }If you use: static if (is(typeof(T[0])) it will work for user-defined types.
Sep 27 2007
Christian and Don, thanks for you help. Here is what i do now. 1) it is modular 2) is dose not need the clumsy yx!() notation. thanks again, oliver ----------- import std.stdio; bool isIndexed(T)(T) { return is( typeof(T[0]) ); } bool isDoubleIndexed(T)(T) { return is( typeof(T[0][0]) ); } bool isSliced(T)(T) { return is( typeof(T[0..0]) ); } bool isArray(T)(T expr) { return isIndexed(expr); } bool isMatrix(T)(T expr) { return isIndexed(expr) && isDoubleIndexed(expr); } bool isBlubb(T)(T expr) { return !isMatrix(expr); } void main () { double s = 1.; double[] v = [1.,2.]; double[][] m = [[1.,2.]]; writefln("s: ", isArray(s), " ", isMatrix(s) ); writefln("v: ", isArray(v), " ", isMatrix(v) ); writefln("m: ", isArray(m), " ", isMatrix(m) ); writefln("b: ", isBlubb(v), " ", isBlubb(m) ); }
Sep 28 2007