www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why emsi containers have disabled this(this) ?

reply Luis <luis.panadero gmail.com> writes:
So, I'm writing my own implementation of sparse sets, and I take 
as reference emsi_containers for allocator usage. I saw that they 
have disabled postblit operator... But i don't understand exactly 
why. In special, when they implement InputRange over the 
containers, but having disabled postblit, make nearly useless (at 
least as I see on this old post 
https://forum.dlang.org/thread/n1sutu$1ugm$1 digitalmars.com?page=1 )

Taking a look to std.container.array, I see that it have postblit 
disabled, but here the range interface isn't implemented. Instead 
it's recommended to do a slice, where apply range algorithms.

I should take this way (ie. forgot to implement front and 
popFront)? I actually have postblit disabled and implemented 
InputForward, but as I say, this make it useless as range. I 
need, like std.container.array, to use slice for do a foreach or 
any range algorithm.
May 19 2020
next sibling parent Mike Parker <aldacron gmail.com> writes:
On Tuesday, 19 May 2020 at 20:51:01 UTC, Luis wrote:
 So, I'm writing my own implementation of sparse sets, and I 
 take as reference emsi_containers for allocator usage. I saw 
 that they have disabled postblit operator... But i don't 
 understand exactly why. In special, when they implement 
 InputRange over the containers, but having disabled postblit, 
 make nearly useless (at least as I see on this old post 
 https://forum.dlang.org/thread/n1sutu$1ugm$1 digitalmars.com?page=1 )

 Taking a look to std.container.array, I see that it have 
 postblit disabled, but here the range interface isn't 
 implemented. Instead it's recommended to do a slice, where 
 apply range algorithms.
In the source for the EMSI containers, they provide opSlice that returns an internal Range type. And not all of the containers implement InputRange. SList does, but HashSet does not.
 I should take this way (ie. forgot to implement front and 
 popFront)? I actually have postblit disabled and implemented 
 InputForward, but as I say, this make it useless as range. I 
 need, like std.container.array, to use slice for do a foreach 
 or any range algorithm.
As a general rule of thumb, containers *should not* be used as InputRanges. And that includes ForwardRange, BidirectionalRange, and RandomAccessRange (each range interface builds upon the one before--simply implementing `save` does not make a ForwardRange unless the type also has the InputRange interface). Input ranges are intended to be consumed. At the end of an iteration, they should be empty. The convention is to obtain a range by slicing the container. So your containers should implement opSlice and return an anonymous range type just like std.container.array, containers.hashset, containers.slist, etc. do. Then iteration becomes: foreach(elem; container[]) { } // The range has been consumed, but the container still holds all the elements.
May 19 2020
prev sibling parent Dukc <ajieskola gmail.com> writes:
On Tuesday, 19 May 2020 at 20:51:01 UTC, Luis wrote:
 I saw that they have postblit operator... But i don't 
 understand exactly why. In special, when they implement 
 InputRange over the containers, but having disabled postblit, 
 make nearly useless (at least as I see on this old post 
 https://forum.dlang.org/thread/n1sutu$1ugm$1 digitalmars.com?page=1 )
You have to understand the memory management difference between EMSI-containers and regular D slices. A normal slice won't worry about freeing the memory used. It just assumes that either the garbage collector will take care of it (the usual case), or that the code will tell manually when the memory really needs to be freed (possibly by some other reference to the same memory). EMSI-containers, however, are designed to free their memory after use themselves. They do it by the Resource Acquisition Is Initialization principle: when the container gets deleted, the underlying data gets freed right away. This leads to that there must be only one container using the same memory. It would not do to make a copy of it, unless it's a deep copy (Deep copy means that also the underlying memory is copied. It tends to take long.). This is the reason that postblits are disabled in EMSI-containers. It wants to protect you from accidents. If you want to store the same container in many places, store references to it instead. And when iterating over it, you get the underlying range first, like Mike said. The underlying range can likely be copied freely.
May 20 2020