Generic const - a non-functional view

Steven Schveighoffer schveiguy at yahoo.com
Wed Jun 25 10:05:08 PDT 2008


"Jason House" wrote
> Steven Schveighoffer Wrote:
>
>> "Jason House" wrote
>> > A lot of times, when I think about tail const/mixed const/mutable/..., 
>> > I
>> > start thinking about arrays.
>> > AKA:
>> >  T[] vs. array!(T)
>> >  const(T)[] vs. array!(const(T)) vs. const!(element)(array!(T))
>
> I probably should have stated that arrays have special status in D.  As 
> built in containers, they have support for for tail const while other 
> objects don't have that luxury.  I implicitly measure the quality of a 
> const proposal by how it can implement an alternate to arrays without the 
> syntactic sugar arrays provide.

Ah, I now understand what you meant.  Yes, it can be done, just like you 
say.

const alias element;

class array(T){
   typedef element(T) elem;
   elem[] contents; // same as elem contents[] I think
}

the tag is not in itself const.  It is a noop when not selected for 
const/invariant.

So array!(T) becomes:

{
   typedef T elem;
   elem[] contents;
}

And const!(element)(array!(T)) becomes:

{
   typedef const(T) elem;
   elem[] contents;  // which is now const(T)[]
}

>> or const!(element)(T)[]
>>
>> or
>>
>> alias const!(element) eleconst;
>>
>> eleconst(T)[]
>
> What's the difference between const!(element)(T)[] and const(T)[]?  I 
> believe this is more a misunderstanding of what I was driving at.

Yes, I misunderstood you.  const!(element)(T)[] and const(T)[] are different 
depending on what T is.  If T is a struct:

struct T
{
   element int x;
   int y;
}

Then const(T) yields:

{
   const int x;
   const int y;
}

and const!(element)(T) yields:

{
   const int x;
   int y;
}

>  Consider this template:
>
> class array(T){
>  typedef element T elem;
>  elem contents[];
> }
>
> Maybe I got the syntax wrong, but the basic idea is that T and element are 
> really the same kind of thing.  array!(const T) and 
> const!(element)(array!(T)) are different types.  Should they be?  I don't 
> think so.  There's still something buried in a tail const scheme that 
> still needs to get fleshed out, somehow...

Tail const is much more possible with the const scheme I outlined.  Your 
example is not really relevant because the entire set of members is marked 
by a tag.  This is no different than today's const.

Basically, as a simple rough explanation, what I propose allows you to 
direct const to apply only to certain pieces of a struct or class, instead 
of always affecting the whole thing.  Tail const is possible because you can 
tag only the 'pointed to' data and const-ify only that part.

Another aspect is this:

array!(T) and array!(const T) are not implicitly castable, because they are 
two separate types.  e.g.:

array!(T) t = new array!(T)(5); // array of 5 Ts

const(array!(T)) t2 = t; // ok, t2 is the same type, but with a const 
modifier.

array!(const T) t3 = t; // error, incompatible types

const!(element)(array!(T)) t4 = t; // ok, because t4 is the same type, but 
with a const modifier.

-Steve 





More information about the Digitalmars-d mailing list