digitalmars.D - Stripping away const/invariant in D 2.0
- Daniel Keep (28/28) Aug 28 2007 I've been trying to work this out for a few hours now, and I'm drawing a
- Bruno Medeiros (7/30) Aug 28 2007 Use "typeof(T)". For example if T is invariant char , then typeof(T) ==
- Daniel Keep (5/8) Aug 28 2007 That's... weird. But it works. Thanks very muchly :)
- Christian Kamm (23/30) Aug 28 2007 This works for plan data like char (since const(char) really is the same
- Daniel Keep (3/40) Aug 28 2007 Shouldn't those be typeof(var).stringof and Q.stringof?
- Christian Kamm (4/26) Aug 28 2007 Yes, I simply forgot about the existence of strongof for a moment. With ...
- Bruno Medeiros (8/19) Aug 28 2007 I know that, that's what I meant when I said it removes "the top level"
- Christian Kamm (7/19) Aug 28 2007 Bruno Medeiros wrote:
-
Stewart Gordon
(46/52)
Aug 28 2007
I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T). This came up because of my templated join function which takes an array of arrays, a separator, and joins all the arrays together. For instance: ["foo","bar","baz"].join(", ") == "foo, bar, baz" The problem is when the arguments are some combination of const and/or invariant. In order to efficiently do the join, it allocates a result array large enough for the full result, then fills it in using slicing. Problem is, what type does it use? Given: T[] join(T,U)(in T[][] parts, in U[] sep=null) There doesn't appear to be any way to derive a mutable version of T or U. I've tried is( T V : const V ) and is( T V == const V ) as well as various array tricks, but nothing seems to be working. In the two "is" cases, V is *always* the same type as T. So unless I've completely missed something, I think one of the following needs to be added: 1. Support for is( T U == const ) and is( T U == invariant ), where U becomes a mutable version of T, 2. a new __traits form: __traits(mutableTypeOf, T) or 3. a new `mutable` keyword that works analogously to const and invariant, except that it strips off const and invariant. I also feel that these constructs should do this constness stripping *only* one level deep (so mutable const(char)[][] is (const(char)[])[] -- removing all levels of constness can be done using a recursive template.) Thoughts (or maybe even corrections? :) ) -- Daniel
Aug 28 2007
Daniel Keep wrote:I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T). This came up because of my templated join function which takes an array of arrays, a separator, and joins all the arrays together. For instance: ["foo","bar","baz"].join(", ") == "foo, bar, baz" The problem is when the arguments are some combination of const and/or invariant. In order to efficiently do the join, it allocates a result array large enough for the full result, then fills it in using slicing. Problem is, what type does it use? Given: T[] join(T,U)(in T[][] parts, in U[] sep=null) There doesn't appear to be any way to derive a mutable version of T or U. I've tried is( T V : const V ) and is( T V == const V ) as well as various array tricks, but nothing seems to be working. In the two "is" cases, V is *always* the same type as T.Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 28 2007
Bruno Medeiros wrote:Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant.That's... weird. But it works. Thanks very muchly :) I still think having something a little more... consistent with existing idioms would be good, though. -- Daniel
Aug 28 2007
This works for plan data like char (since const(char) really is the same type as char, if I understand it right - there's no 'tail' that could be const), but not for reference types: class T {} const(T) var; writefln(typeid(typeof(var))); produces const T However, I think templates are broken with regard to const, since: class T {} const(T) var; pragma(msg, typeof(var)); errors with consttest.d(14): Error: string expected for message, not 'const T' and template Foo(Q) { pragma(msg, Q); } class T {} const(T) var; Foo!(typeof(var)); errors with consttest.d(7): pragma msg string expected for message, not 'T'I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T).Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant.
Aug 28 2007
Christian Kamm wrote:Shouldn't those be typeof(var).stringof and Q.stringof? -- DanielThis works for plan data like char (since const(char) really is the same type as char, if I understand it right - there's no 'tail' that could be const), but not for reference types: class T {} const(T) var; writefln(typeid(typeof(var))); produces const T However, I think templates are broken with regard to const, since: class T {} const(T) var; pragma(msg, typeof(var)); errors with consttest.d(14): Error: string expected for message, not 'const T' and template Foo(Q) { pragma(msg, Q); } class T {} const(T) var; Foo!(typeof(var)); errors with consttest.d(7): pragma msg string expected for message, not 'T'I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T).Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant.
Aug 28 2007
Yes, I simply forgot about the existence of strongof for a moment. With that change you'd get "const T" instead of the first and "T" instead of the second error message. ChristianHowever, I think templates are broken with regard to const, since: class T {} const(T) var; pragma(msg, typeof(var)); errors with consttest.d(14): Error: string expected for message, not 'const T' and template Foo(Q) { pragma(msg, Q); } class T {} const(T) var; Foo!(typeof(var)); errors with consttest.d(7): pragma msg string expected for message, not 'T'Shouldn't those be typeof(var).stringof and Q.stringof?
Aug 28 2007
Christian Kamm wrote:I know that, that's what I meant when I said it removes "the top level" const/invariant. Maybe not the best of terminology, it was just something that I had used before. And I haven't read about this new head/tail stuff yet. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DThis works for plan data like char (since const(char) really is the same type as char, if I understand it right - there's no 'tail' that could be const), but not for reference types:I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T).Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant.
Aug 28 2007
Bruno Medeiros wrote:Christian Kamm wrote:Use "typeof(T)". For example if T is invariant char , then typeof(T) == char. typeof() kinda works like a declaration, so it removes the top level const/invariant.Bruno Medeiros wrote:This works for plan data like char (since const(char) really is the same type as char, if I understand it right - there's no 'tail' that could be const), but not for reference types:I know that, that's what I meant when I said it removes "the top level" const/invariant. Maybe not the best of terminology, it was just something that I had used before. And I haven't read about this new head/tail stuff yet.Ah, I misunderstood then. Also, I didn't know that stripping of the 'top level' const would only happen in declarations, so Stewart Gordon's solution baffled me at first. Christian
Aug 28 2007
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:fb0o30$2fd4$1 digitalmars.com...I've been trying to work this out for a few hours now, and I'm drawing a blank. In D 2.0, there doesn't appear to be any way of deriving the type of T given either (const T) or (invariant T).<snip>T[] join(T,U)(in T[][] parts, in U[] sep=null) There doesn't appear to be any way to derive a mutable version of T or U.Here's some code that works: ---------- template unconst(T) { pragma(msg, "unconst(" ~ T.stringof ~ ")"); alias unc!(T).u unconst; pragma(msg, "unconst(" ~ T.stringof ~ ") -> " ~ unconst.stringof); } template unc(T) { T dummy; alias typeof(dummy) u; } template unc(T : T[]) { alias unc!(T).u[] u; } alias int[] arrayType1; alias const(int)[] arrayType2; alias invariant(int)[] arrayType3; alias const(int[]) arrayType4; alias const(const(int)[]) arrayType5; alias const(invariant(int)[]) arrayType6; alias invariant(int[]) arrayType7; alias invariant(const(int)[]) arrayType8; alias invariant(invariant(int)[]) arrayType9; unconst!(arrayType1) array1; static assert (is(typeof(array1) == int[])); unconst!(arrayType2) array2; static assert (is(typeof(array2) == int[])); unconst!(arrayType3) array3; static assert (is(typeof(array3) == int[])); unconst!(arrayType4) array4; static assert (is(typeof(array4) == int[])); unconst!(arrayType5) array5; static assert (is(typeof(array5) == int[])); unconst!(arrayType6) array6; static assert (is(typeof(array6) == int[])); unconst!(arrayType7) array7; static assert (is(typeof(array7) == int[])); unconst!(arrayType8) array8; static assert (is(typeof(array8) == int[])); unconst!(arrayType9) array9; static assert (is(typeof(array9) == int[])); ---------- Stewart.
Aug 28 2007