Decision on container design

Michel Fortin michel.fortin at michelf.com
Fri Jan 28 18:12:31 PST 2011


On 2011-01-28 20:10:06 -0500, "Denis Koroskin" <2korden at gmail.com> said:

> Unfortunately, this design has big issues:
> 
> 
> void fill(Appender appender)
> {
>      appender.put("hello");
>      appender.put("world");
> }
> 
> void test()
> {
>      Appender<string> appender;
>      fill(appender); // Appender is supposed to have reference semantics
>      assert(appender.length != 0); // fails!
> }
> 
> Asserting above fails because at the time you pass appender object to 
> the  fill method it isn't initialized yet (lazy initialization). As 
> such, a  null is passed, creating an instance at first appending, but 
> the result  isn't seen to the caller.

That's indeed a problem. I don't think it's a fatal flaw however, given 
that the idiom already exists in AAs.

That said, the nice thing about my proposal is that you can easily 
reuse the Impl to create a new container to build a new container 
wrapper with the semantics you like with no loss of efficiency.

As for the case of Appender... personally in the case above I'd be 
tempted to use Appender.Impl directly (value semantics) and make fill 
take a 'ref'. There's no point in having an extra heap allocation, 
especially if you're calling test() in a loop or if there's a good 
chance fill() has nothing to append to it.

That's the issue with containers. The optimal semantics always change 
depending on the use case.


> An explicit initialization is needed to work around this design issue. 
> The  worst thing is that in many cases it would work fine (you might 
> have  already initialized it indirectly) but sometimes you get 
> unexpected  result. I got hit by this in past, and it wasn't easy to 
> trace down.
> 
> As such, I strongly believe containers either need to have copy 
> semantics,  or be classes. However, copy semantics contradicts with the 
> "cheap copy  ctor" idiom because you need to copy all the elements from 
> source  container.

Personally, I'm really concerned by the case where you have a container 
of containers. Class semantics make things really complicated as you 
always have to initialize everything in the container explicitly; value 
semantics makes things semantically easier but quite inefficient as 
moving elements inside of the outermost container implies copying the 
containers. Making containers auto-initialize themselves on first use 
solves the case where containers are references-types; making 
containers capable of using move semantics solves the problem for 
value-type containers.


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



More information about the Digitalmars-d mailing list