std.container and classes

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Dec 17 15:31:46 PST 2011


On 12/13/11 9:08 PM, Jonathan M Davis wrote:
> Is the plan for std.container still to have all of its containers be final
> classes (classes so that they're reference types and final so that their
> functions are inlinable)? Or has that changed? I believe that Andrei said
> something recently about discussing reference counting and containers with
> Walter.
>
> The reason that I bring this up is that Array and SList are still structs, and
> the longer that they're structs, the more code that will break when they get
> changed to classes. Granted, some level of code breakage may occur when we add
> custom allocators to them, but since that would probably only affect the
> constructor (and preferably wouldn't affect anything if you want to simply
> create a container with the GC heap as you would now were Array and SList
> classes), the breakage for that should be minimal.
>
> Is there any reason for me to not just go and make Array and SList final
> classes and create a pull request for it?
>
> - Jonathan M Davis

Apologies for being slow on this. It may be a fateful time to discuss 
that right now, after all the discussion of what's appropriate for 
stdlib vs. application code etc.

As some of you know, Walter and I went back and forth several times on 
this. First, there was the issue of making containers value types vs. 
reference types. Making containers value types would be in keep with the 
STL approach. However, Walter noted that copying entire containers by 
default is most often NOT desirable and there's significant care and 
adornments in C++ programs to make sure that that default behavior is 
avoided (e.g. adding const& to function parameters).

So we decided to make containers reference types, and that seemed to be 
a good choice.

The second decision is classes vs. structs. Walter correctly pointed out 
that the obvious choice for defining a reference type in D - whether the 
type is momonorphic or polymorphic - is making it a class. If containers 
aren't classes, the reasoning went, it means we took a wrong step 
somewhere; it might mean our flagship abstraction for reference types is 
not suitable for, well, defining a reference type.

Fast forward a couple of months, a few unslept nights, and a bunch of 
newsgroup and IRC conversations. Several additional pieces came together.

The most important thing I noticed is that people expect standard 
containers to have sophisticated memory management. Many ask not about 
containers as much as "containers with custom allocators". Second, 
containers tend to be large memory users by definition. Third, 
containers are self-contained (heh) and relatively simple in terms of 
what they model, meaning that they _never_ suffer from circular 
references, like general entity types might.

All of these arguments very strongly suggest that many want containers 
to be types with deterministic control over memory and accept 
configurable allocation strategies (regions, heap, malloc, custom). So 
that would mean containers should be reference counted structs.

This cycle of thought has happened twice, and the evidence coming the 
second time has been stronger. The first time around I went about and 
started implementing std.container with reference counting in mind. The 
code is not easy to write, and is not to be recommended for most types, 
hence my thinking (at the end of the first cycle) that we should switch 
to class containers. One fear I have is that people would be curious, 
look at the implementation of std.container, and be like "so am I 
expected to do all this to define a robust type"? I start to think that 
the right answer to that is to improve library support for good 
reference counted types, and define reference counted struct containers 
that are deterministic.

Safety is also an issue. I was hoping I'd provide safety as a policy, 
e.g. one may choose for a given container whether they want safe or not 
(and presumably fast). I think it's best to postpone that policy and 
focus for now on defining safe containers with safe ranges. This 
precludes e.g. using T[] as a range for Array!T.

Please discuss.


Andrei


More information about the Digitalmars-d mailing list