Decision on container design

Michel Fortin michel.fortin at michelf.com
Fri Jan 28 18:15:01 PST 2011


On 2011-01-28 19:00:02 -0500, Tomek Sowiński <just at ask.me> said:

> Michel Fortin napisał:
> 
>> We already argument this over and over in the past. First, I totally
>> acknowledge that C++ style containers have a problem: they make it
>> easier to copy the content than pass it by reference. On the other side
>> of the spectrum, I think that class semantics makes it too easy to have
>> null dereferences, it's easy to get lost when you have a container of
>> containers.
>> 
>> I have some experience with containers having class-style semantics: in
>> Objective-C, I ended up creating a set of macro-like functions which I
>> use to initialize containers whenever I use them in case they are null.
>> And I had to do more of these utility functions to handle a particular
>> data structure of mine which is a dictionary of arrays of objects. In
>> C++, I'd have declared this as a "map< string, vector< Object > >" and
>> be done with it; no need for special care initializing each vector, so
>> much easier than in Objective-C.
>> 
>> I agree that defining structs to have reference semantics as you have
>> done is complicated. But I like the lazy initialization, and we have a
>> precedent for that with AAs (ideally, AAs would be a compatible
>> container too). Can't we just use the GC instead of reference counting?
>> I'd make things much easier. Here is a implementation:
>> 
>> 	struct Container
>> 	{
>> 		struct Impl { ... }
>> 
>> 		private Impl* _impl;
>> 		ref Impl impl() @property
>> 		{
>> 			if (!impl) impl = new Impl;
>> 			return *impl;
>> 		}
>> 	
>> 		alias impl this;
>> 	}
>> 
>> I also believe reference semantics are not to be used everywhere, even
>> though they're good most of the time. I'd like to have a way to bypass
>> it and get a value-semantic container. With the above, it's easy as
>> long as you keep Container.Impl public:
>> 
>> 	void main() {
>> 		Container      lazyHeapAllocatedContainer;
>> 		Container.Impl stackAllocatedContainer;
>> 	}
>> 
>> 	void MyObject {
>> 		Container.Impl listOfObjects;
>> 	}
> 
> Is there anything implementation specific in the outer struct that provides
> ref semantics to Impl? If not, Container could be generic, parametrized by
> Impl type.

You could provide an implementation-specific version of some functions 
as an optimization. For instance there is no need to create the Impl 
when asking for the length, if the pointer is null, length is zero. 
Typically, const function can be implemented in the outward container 
with a shortcut checking for null.


> Overall, I think a value-like implementation in a referency wrapper is 
> a clear-cut idiom, bringing order to otherwise messy struct-implemented 
> ref-semantics. Do you know of a existing collection library that 
> exploits this idea?

No. Only associative arrays in D do that, that I know of.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list