digitalmars.D.learn - Distinguishing between const and non-const variable in a template?
- renoX (66/66) Feb 21 2007 Hello,
- mario pernici (11/86) Feb 22 2007 Maybe you can use something like this
- renoX (8/33) Feb 22 2007 Very nice, thanks!
- Deewiant (6/43) Feb 22 2007 He probably just figured it out: you can't take the address of a constan...
- mario pernici (7/50) Feb 22 2007 I learned about static if (is(typeof(...)))
- renoX (4/54) Feb 22 2007 Mmm; how could s doesn't exist?
- Chris Nicholson-Sauls (11/68) Feb 22 2007 version (Something) import some.convoluted.library;
- Chris Nicholson-Sauls (7/78) Feb 22 2007 Yes its a contrived example, but its possible. (And yes I know in this ...
- Tyler Knott (18/33) Feb 22 2007 D is statically typed, but that has nothing to do with why the second te...
- renoX (3/52) Feb 22 2007 Very clear explanation, thanks!
Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not? My goal is: if the parameter isn't a const char[]: leave its name unchanged so that it's parsed by the writef at runtime, if it is a const char[]: parse it myself with the new syntax. Regards, renoX template FindChar(char[] A, char B) { static if (A.length == 0) { const int FindChar = -1; } else static if (A[0] == B) { const int FindChar = 0; } else static if (-1 == FindChar!(A[1..$], B)) { const int FindChar = -1; } else { const int FindChar = 1 + FindChar!(A[1..$], B); } } template FmtString(char[] F, A...) { static if (F.length == 0) static if (A.length) const char[] FmtString = "\"," ~ Fmt!(A); else const char[] FmtString = "\""; else static if (F.length == 1) static if (A.length) const char[] FmtString = F[0] ~ "\"," ~ Fmt!(A); else const char[] FmtString = F[0] ~ "\""; else static if (F[0..2] == "%%") const char[] FmtString = "%%" ~ FmtString!(F[2..$], A); else static if (F[0..2] == "%{") { // get the variable name between %{ and } static if (FindChar!(F, '}') <= 2) static assert(0, "format %{} incorrect in '" ~ F ~ "'"); const char[] FmtString = "%s\"," ~ F[2..FindChar!(F,'}')] ~ ",\"" ~ FmtString!(F[1+FindChar!(F,'}')..$], A); } else const char[] FmtString = F[0] ~ FmtString!(F[1..$], A); } template Fmt(A...) { //static assert(0, cast(char*)A[0]); static if (A.length == 0) const char[] Fmt = ""; else static if (is(typeof(A[0]) : char[])) const char[] Fmt = "\"" ~ FmtString!(A[0], A[1..$]); else static if (A.length == 1) const char[] Fmt = A[0].stringof; else const char[] Fmt = A[0].stringof ~ "," ~ Fmt!(A[1..$]); } template Putf(A...) { const char[] Putf = "writef(" ~ Fmt!(A) ~ ");"; }
Feb 21 2007
renoX Wrote:Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not? My goal is: if the parameter isn't a const char[]: leave its name unchanged so that it's parsed by the writef at runtime, if it is a const char[]: parse it myself with the new syntax. Regards, renoX template FindChar(char[] A, char B) { static if (A.length == 0) { const int FindChar = -1; } else static if (A[0] == B) { const int FindChar = 0; } else static if (-1 == FindChar!(A[1..$], B)) { const int FindChar = -1; } else { const int FindChar = 1 + FindChar!(A[1..$], B); } } template FmtString(char[] F, A...) { static if (F.length == 0) static if (A.length) const char[] FmtString = "\"," ~ Fmt!(A); else const char[] FmtString = "\""; else static if (F.length == 1) static if (A.length) const char[] FmtString = F[0] ~ "\"," ~ Fmt!(A); else const char[] FmtString = F[0] ~ "\""; else static if (F[0..2] == "%%") const char[] FmtString = "%%" ~ FmtString!(F[2..$], A); else static if (F[0..2] == "%{") { // get the variable name between %{ and } static if (FindChar!(F, '}') <= 2) static assert(0, "format %{} incorrect in '" ~ F ~ "'"); const char[] FmtString = "%s\"," ~ F[2..FindChar!(F,'}')] ~ ",\"" ~ FmtString!(F[1+FindChar!(F,'}')..$], A); } else const char[] FmtString = F[0] ~ FmtString!(F[1..$], A); } template Fmt(A...) { //static assert(0, cast(char*)A[0]); static if (A.length == 0) const char[] Fmt = ""; else static if (is(typeof(A[0]) : char[])) const char[] Fmt = "\"" ~ FmtString!(A[0], A[1..$]); else static if (A.length == 1) const char[] Fmt = A[0].stringof; else const char[] Fmt = A[0].stringof ~ "," ~ Fmt!(A[1..$]); } template Putf(A...) { const char[] Putf = "writef(" ~ Fmt!(A) ~ ");"; }Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }
Feb 22 2007
mario pernici a écrit :renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
renoX wrote:mario pernici a écrit :He probably just figured it out: you can't take the address of a constant, so is(typeof(&s)) is false if s is a constant. I'm not sure about the necessity of the is(typeof(s)) in the else case, though. -- Remove ".doesnotlike.spam" from the mail address.renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
Deewiant Wrote:renoX wrote:I learned about static if (is(typeof(...))) from the post by Kirk McDonald in the recent thread "Testing if a function is defined in a module". The else clause static if(is(typeof(s))) is to make sure that s exists.mario pernici a écrit :He probably just figured it out: you can't take the address of a constant, so is(typeof(&s)) is false if s is a constant. I'm not sure about the necessity of the is(typeof(s)) in the else case, though.renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
mario pernici a écrit :Deewiant Wrote:Mmm; how could s doesn't exist? D is supposed to be a statically typed language.. renoXrenoX wrote:I learned about static if (is(typeof(...))) from the post by Kirk McDonald in the recent thread "Testing if a function is defined in a module". The else clause static if(is(typeof(s))) is to make sure that s exists.mario pernici a écrit :He probably just figured it out: you can't take the address of a constant, so is(typeof(&s)) is false if s is a constant. I'm not sure about the necessity of the is(typeof(s)) in the else case, though.renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
renoX wrote:mario pernici a écrit :version (Something) import some.convoluted.library; else import some.limited.standIn; // ... much later in module static if(is(typeof(someSymbolNotInStandIn))) { // ... do things usual way } else { // ... do it a work-around way for the stand in's case } -- Chris Nicholson-SaulsDeewiant Wrote:Mmm; how could s doesn't exist? D is supposed to be a statically typed language.. renoXrenoX wrote:I learned about static if (is(typeof(...))) from the post by Kirk McDonald in the recent thread "Testing if a function is defined in a module". The else clause static if(is(typeof(s))) is to make sure that s exists.mario pernici a écrit :He probably just figured it out: you can't take the address of a constant, so is(typeof(&s)) is false if s is a constant. I'm not sure about the necessity of the is(typeof(s)) in the else case, though.renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
Chris Nicholson-Sauls wrote:renoX wrote:Yes its a contrived example, but its possible. (And yes I know in this case version(Something) would be better than static-if, but what if the stand-in is subject to change without notice?) Another use case: a hypothetical GUI library that, in the absence of a main routine, uses its own generic one? (Wouldn't work all GUI lib designs, of course.) -- Chris Nicholson-Saulsmario pernici a écrit :version (Something) import some.convoluted.library; else import some.limited.standIn; // ... much later in module static if(is(typeof(someSymbolNotInStandIn))) { // ... do things usual way } else { // ... do it a work-around way for the stand in's case } -- Chris Nicholson-SaulsDeewiant Wrote:Mmm; how could s doesn't exist? D is supposed to be a statically typed language.. renoXrenoX wrote:I learned about static if (is(typeof(...))) from the post by Kirk McDonald in the recent thread "Testing if a function is defined in a module". The else clause static if(is(typeof(s))) is to make sure that s exists.mario pernici a écrit :He probably just figured it out: you can't take the address of a constant, so is(typeof(&s)) is false if s is a constant. I'm not sure about the necessity of the is(typeof(s)) in the else case, though.renoX Wrote:[cut]Hello, I'm trying to improve format string by allowing the format " ... %{x} ...", my problem is that when I give a non-const char[] parameter in mixin(Putf!(foo)); then the template fail.. How can I reliably detect in a template if the parameter is a constant or not?Maybe you can use something like this const char[] s = "ab"; static if(is(typeof(&s))) { writefln(s, " not constant"); } else { static if(is(typeof(s))) { writefln(s, " constant"); } }Very nice, thanks! I'm curious: how did you find this?? I don't recall seeing it in the documentation and it looks kind of magical to me.. Thanks again, renoX
Feb 22 2007
renoX wrote:mario pernici a écrit :D is statically typed, but that has nothing to do with why the second test is needed. Here's a quote from the language spec on the typeof(Expression) construct (http://www.digitalmars.com/d/declaration.html):The else clause static if(is(typeof(s))) is to make sure that s exists.Mmm; how could s doesn't exist? D is supposed to be a statically typed language.. renoXExpression is not evaluated, just the type of it is generated: void func() { int i = 1; typeof(++i) j; // j is declared to be an int, i is not incremented printf("%d\n", i); // prints 1 }And then if you look at the documentation for IsExpression, you'll see that invalid types used in the context of an IsExpression won't error, but instead cause the IsExpression to return 0 (false). When you combine these two properties, it is legal and valid for D code to take the type of an undeclared variable (resulting in an invalid type) inside an IsExpression; e.g.: void main() { int foo; static assert(is(typeof(foo)), "foo is a valid variable."); //Valid, doesn't trip static assert(is(typeof(undeclaredVariable)), "undeclaredVariable is invalid."); //Valid, trips typeof(foo) bar; //Valid, bar is an int typeof(undeclaredVariable) bar; //"Error: undefined identifier undeclaredVariable" } This is why two tests are required for Mario Pernici's const dectector. The first test determines if you can take the address of the variable, which fails for both const and invalid variables. Then, it needs to make sure the variable actually exists by taking its type (invalid variables will fail here, but everything else will pass).
Feb 22 2007
Tyler Knott a écrit :renoX wrote:Very clear explanation, thanks! renoXmario pernici a écrit :D is statically typed, but that has nothing to do with why the second test is needed. Here's a quote from the language spec on the typeof(Expression) construct (http://www.digitalmars.com/d/declaration.html): > Expression is not evaluated, just the type of it is generated: > void func() > { int i = 1; > typeof(++i) j; // j is declared to be an int, i is not incremented > printf("%d\n", i); // prints 1 > } And then if you look at the documentation for IsExpression, you'll see that invalid types used in the context of an IsExpression won't error, but instead cause the IsExpression to return 0 (false). When you combine these two properties, it is legal and valid for D code to take the type of an undeclared variable (resulting in an invalid type) inside an IsExpression; e.g.: void main() { int foo; static assert(is(typeof(foo)), "foo is a valid variable."); //Valid, doesn't trip static assert(is(typeof(undeclaredVariable)), "undeclaredVariable is invalid."); //Valid, trips typeof(foo) bar; //Valid, bar is an int typeof(undeclaredVariable) bar; //"Error: undefined identifier undeclaredVariable" } This is why two tests are required for Mario Pernici's const dectector. The first test determines if you can take the address of the variable, which fails for both const and invalid variables. Then, it needs to make sure the variable actually exists by taking its type (invalid variables will fail here, but everything else will pass).The else clause static if(is(typeof(s))) is to make sure that s exists.Mmm; how could s doesn't exist? D is supposed to be a statically typed language.. renoX
Feb 22 2007