Kinds of containers

bitwise via Digitalmars-d digitalmars-d at puremagic.com
Thu Oct 22 09:29:17 PDT 2015


On Thursday, 22 October 2015 at 15:53:21 UTC, Jonathan M Davis 
wrote:
> On Thursday, 22 October 2015 at 15:26:30 UTC, bitwise wrote:
>> On Thursday, 22 October 2015 at 05:09:38 UTC, deadalnix wrote:
>>> The elephant in the room: make the template parameter's type 
>>> qualifier transitive with the collection's qualifier.
>>
>> Not sure exactly what you mean by this. Currently, Ranges and 
>> Cursors are templated on the type of the container, so If the 
>> container is const, you get a const Range or Cursor. I haven't 
>> gone over the containers with a fine tooth comb yet, so if you 
>> can point anything out, it would be helpful.
>
> LOL. const and ranges do _not_ mix well - in part because 
> popFront inherently requires that the range be mutable - but 
> mostly because of templates.
>
> If you have const(T)[], and you then you slap another const on 
> it - const(const(T)[]) - the compiler knows full-well that 
> that's equivalent to const(T[]). In fact, it even knows that if 
> you slice a const(T[]), it's perfectly safe for the result to 
> be const(T)[], because it's a different array, and by keeping 
> the elements const, it won't screw with the elements of the one 
> it was sliced from (since they're the same elements). But what 
> about with ranges?
>
> If you have Range!(const T) and then you do const Range!(const 
> T), is that equivalent to const(Range!T)? Maybe, maybe not. The 
> compiler certainly doesn't treat it as such - and it can't. 
> Similarly, if you have const(Range!T) or const(Range!(const 
> T)), and you slice the range, the compiler doesn't magically 
> know that the slice can be Range!(const T). As far as the 
> compiler is concerned, we're dealing with different types here. 
> After all, what if the Range type had something like this in it
>
> struct Range(T)
> {
>     static if(is(T == const))
>     {
>         // do something differently here
>     }
> }
>
> The entire guts of Range could be completely different simply 
> due to a difference in constness. Template constraints could 
> also be used to overload on constness. So, unlike with arrays, 
> there really is no guarantee that two instantiations of the 
> same template are at all related to one another even when they 
> seem to only differ by constness. Heck, to even attempt to have 
> a range type which has an opSlice which returns a tail-const 
> slice _requires_ that you have static ifs checking for 
> constness, or you end up with a recursive template 
> instantiation.
>
> So, even without getting containers involved, const and ranges 
> do _not_ mix well, even though const and arrays get along 
> fantastically. And when you have to start considering what a 
> containers opSlice is going to return an how it's going to deal 
> with const, things get that much worse (e.g. is it even going 
> to work to have opSlice be const). And depending on the 
> container's internals, having a range only have const access to 
> its underlying container could be problematic. IIRC, 
> std.container.Array has had some issues with const related to 
> its internals not having been designed in a way that worked 
> well with D's const.
>
> So, const throws a very interesting wrench into the mix when 
> dealing with either ranges or containers, and the fact that 
> const(Foo!T) is not necessarily the same as const(Foo!(const 
> T)) can definitely be problematic.
>
> - Jonathan M Davis

Maybe look at the code next time before you LOL......

      Bit



More information about the Digitalmars-d mailing list