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