[typing] Type-erasure re generics

Steven Schveighoffer schveiguy at yahoo.com
Wed Sep 29 12:36:02 PDT 2010


On Wed, 29 Sep 2010 15:16:28 -0400, Jonathan M Davis <jmdavisProg at gmx.com>  
wrote:

> On Wednesday, September 29, 2010 11:54:30 Steven Schveighoffer wrote:
>> I think it may have to be more than just const:
>>
>> class C(T)
>> {
>>     static T globalval;
>> }
>>
>> class A {}
>> class B : A {}
>>
>> void foo(C!B c)
>> {
>>    const(C!A) c2 = c;
>>    c2.globalval = new A;
>> }
>>
>> If the entire class is marked as pure (with pure defined as weak purity  
>> a
>> la Don's idea) that might work as setting globalval would be illegal.
>
> Ah. Once you get beyond arrays, you have the issue of the container type  
> itself
> being different. Hmmm. For C#, you might be okay since they're all  
> technically
> the same type anyway (and would share any globals), but for D, the two  
> types
> could have absolutes nothing in common with one another. All class  
> variables
> would be by definition local to each instantiation, so no const would  
> not be
> enough.
>
> But worse still, consider this: With templates, you could have a  
> container type
> which used completely different implementations depending on the type(s)  
> you use
> to instantiate it.

Excellent point.  If this *were* a feature we wanted, the compiler would  
have to make that determination (I think it could be done, but I'm not  
sure of all the nuances).

> It could use an array for ints, a hash table for floats, and a
> red-black tree for everything else.

Wait, the types have to be bit-for-bit compatible, or it doesn't work.   
You can't cast floats to ints without reinterpreting the data.

I don't even think you could do classes to interfaces, because you need to  
do a translation.

> In such a case, would would it even _mean_
> to try and assign one container type to another? Sure, if they're  
> classes, and
> they share the same API, you may be able to get it to work thanks to the  
> fact
> that you're dealing with references.

No, even with that, you brought it up earlier -- class C could say:

static if(is(T == A))
    void anotherfunction() {}

and then the vtable for C!B is different than C!A, even though the vtable  
for B is compatible with the vtable for A.

There has to be some way for the compiler to determine this, but again,  
only if this feature makes sense to implement.

> But for structs? Forget it. Just because
> the types Array!int and Array!float are instantiated from the same  
> template
> doesn't mean that they have anything in common other than the base name.

For floats and ints, yes.  But this doesn't even matter, because it has to  
be bit-for-bit compatible.  There's no way you could case S!int to S!float  
without having to translate everything.

Something like Array!int to Array!(const int) would be feasible.

> The
> only way that you can even consider having containers be effectively in  
> an
> inheritance hiercharcy because their elements are in an inheritence  
> hiearchy is
> if the containers are classes. And since it looks like most - if not all  
> -
> containers in Phobos are going to be structs

All containers in dcollections are classes ;)

> it quickly becomes a moot point
> for anything but arrays. With arrays, you could do it with just  
> constness, I
> think. But for other container types? It _might_ be feasible with  
> classes if you
> could somehow restrict access to all of their class variables and  
> non-pure,
> static member functions, but it_won't work for structs.

I think it can be done, but it may require really strict rules, and those  
rules may not be assertable without some new syntax.

For example, one place where this can be extremely useful is tail-const.   
If S!(T) implicitly casts to S!(const(T)), then we can implement  
tail-const in the library (though I'd prefer a compiler solution).

-Steve


More information about the Digitalmars-d mailing list