## 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"
• Stewart Gordon (46/52) Aug 28 2007
Daniel Keep <daniel.keep.lists gmail.com> writes:
```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
Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
```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
Daniel Keep <daniel.keep.lists gmail.com> writes:
```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
Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
``` 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'
```
Aug 28 2007
Daniel Keep <daniel.keep.lists gmail.com> writes:
```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
```
Aug 28 2007
Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
``` 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
```
Aug 28 2007
Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
```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
```
Aug 28 2007
Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> writes:
```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
```
Aug 28 2007
"Stewart Gordon" <smjg_1998 yahoo.com> writes:
```"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