| Thread overview | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 28, 2007 Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
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
| ||||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | 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 | |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros |
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
| |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros | >> 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.
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'
| |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm |
Christian Kamm 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).
>> 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.
>
> 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'
>
Shouldn't those be typeof(var).stringof and Q.stringof?
-- Daniel
| |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | >> 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'
>>
>
> Shouldn't those be typeof(var).stringof and Q.stringof?
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.
Christian
| |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | "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. | |||
August 28, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | Christian Kamm 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). >> 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. > > 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. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D | |||
August 29, 2007 Re: Stripping away const/invariant in D 2.0 | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Bruno Medeiros | 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. >>> Christian Kamm 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: >> Bruno Medeiros 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. 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 | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply