Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1740

Show
Ignore:
Timestamp:
07/09/10 03:59:53 (14 years ago)
Author:
andrei
Message:

Defined TotalContainer? such that all member functions issue assert(0). That way it's easy to build new containers by copying and pasting TotalContainer?. Also added specialization of Array for bool that stores one bit per element.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/container.d

    r1734 r1740  
    1010 
    1111License: Distributed under the Boost Software License, Version 1.0. 
    1212(See accompanying file LICENSE_1_0.txt or copy at $(WEB 
    1313boost.org/LICENSE_1_0.txt)). 
    1414 
    1515Authors: $(WEB erdani.com, Andrei Alexandrescu) 
    1616 
    1717 */ 
    1818module std.container; 
    1919 
    20 import core.stdc.stdlib, core.stdc.string, std.algorithm, std.contracts
    21     std.conv, std.functional, std.range, std.traits, std.typecons, 
    22     core.memory
     20import core.memory, core.stdc.stdlib, core.stdc.string, std.algorithm
     21    std.conv, std.exception, std.functional, std.range, std.traits, 
     22    std.typecons, std.typetuple
    2323version(unittest) import std.stdio; 
    2424 
    2525/** 
    2626$(D TotalContainer) is an unimplemented container that illustrates a 
    2727host of primitives that a container may define. It is to some extent 
    2828the bottom of the conceptual container hierarchy. A given container 
    2929most often will choose to only implement a subset of these primitives, 
    3030and define its own additional ones. Adhering to the standard primitive 
    3131names below allows generic code to work independently of containers. 
    3232 
     
    3939A container may choose to define additional specific operations. The 
    4040only requirement is that those operations bear different names than 
    4141the ones below, lest user code gets confused. 
    4242 
    4343Complexity of operations should be interpreted as "at least as good 
    4444as". If an operation is required to have $(BIGOH n) complexity, it 
    4545could have anything lower than that, e.g. $(BIGOH log(n)). Unless 
    4646specified otherwise, $(D n) inside a $(BIGOH) expression stands for 
    4747the number of elements in the container. 
    4848 */ 
    49 struct TotalContainer(Whatever
     49struct TotalContainer(T
    5050{ 
    5151/** 
    5252If the container has a notion of key-value mapping, $(D KeyType) 
    5353defines the type of the key of the container. 
    5454 */ 
    55     alias SomeType KeyType; 
     55    alias T KeyType; 
    5656 
    5757/** 
    5858If the container has a notion of multikey-value mapping, $(D 
    5959KeyTypes[k]), where $(D k) is a zero-based unsigned number, defines 
    6060the type of the $(D k)th key of the container. 
    6161 
    6262A container may define both $(D KeyType) and $(D KeyTypes), e.g. in 
    6363the case it has the notion of primary/preferred key. 
    6464 */ 
    65     alias TypeTuple!(Key1, Key2) KeyTypes; 
     65    alias TypeTuple!(T) KeyTypes; 
    6666 
    6767/** 
    6868If the container has a notion of key-value mapping, $(D ValueType) 
    6969defines the type of the value of the container. Typically, a map-style 
    7070container mapping values of type $(D K) to values of type $(D V) 
    71 defines $(D KeyType) to be $(D K), $(D ValueType) to be $(D V), and 
    72 $(D ElementType) to be $(D Tuple!(K, V)). 
    73  */ 
    74     alias SomeType ValueType; 
     71defines $(D KeyType) to be $(D K) and $(D ValueType) to be $(D V). 
     72 */ 
     73    alias T ValueType; 
    7574 
    7675/** 
    7776Defines the container's primary range, which embodies one of the 
    78 archetypal ranges defined in $(XREFMODULE range). 
     77ranges defined in $(XREFMODULE range). 
    7978 
    8079Generally a container may define several types of ranges. 
    8180 */ 
    82     alias SomeType Range; 
     81    struct Range 
     82    { 
     83        /// Range primitives. 
     84        @property bool empty() 
     85        { 
     86            assert(0); 
     87        } 
     88        /// Ditto 
     89        @property T front() 
     90        { 
     91            assert(0); 
     92        } 
     93        /// Ditto 
     94        T moveFront() 
     95        { 
     96            assert(0); 
     97        } 
     98        /// Ditto 
     99        void popFront() 
     100        { 
     101            assert(0); 
     102        } 
     103        /// Ditto 
     104        @property T back() 
     105        { 
     106            assert(0); 
     107        } 
     108        /// Ditto 
     109        T moveBack() 
     110        { 
     111            assert(0); 
     112        } 
     113        /// Ditto 
     114        void popBack() 
     115        { 
     116            assert(0); 
     117        } 
     118        /// Ditto 
     119        T opIndex(size_t i) 
     120        { 
     121            assert(0); 
     122        } 
     123        /// Ditto 
     124        void opIndexAssign(T value, uint i) 
     125        { 
     126            assert(0); 
     127        } 
     128        /// Ditto 
     129        void opIndexOpAssign(string op)(T value, uint i) 
     130        { 
     131            assert(0); 
     132        } 
     133        /// Ditto 
     134        T moveAt(size_t i) 
     135        { 
     136            assert(0); 
     137        } 
     138        /// Ditto 
     139        @property size_t length() 
     140        { 
     141            assert(0); 
     142        } 
     143    } 
    83144 
    84145/** 
    85146Property returning $(D true) if and only if the container has no 
    86147elements. 
    87148 
    88149Complexity: $(BIGOH 1) 
    89150 */ 
    90     @property bool empty(); 
     151    @property bool empty() 
     152    { 
     153        assert(0); 
     154    } 
    91155 
    92156/** 
    93157Returns a duplicate of the container. The elements themselves are not 
    94158transitively duplicated. 
    95159 
    96160Complexity: $(BIGOH n). 
    97161 */ 
    98     @property TotalContainer dup(); 
     162    @property TotalContainer dup() 
     163    { 
     164        assert(0); 
     165    } 
    99166 
    100167/** 
    101168Returns the number of elements in the container. 
    102169 
    103170Complexity: $(BIGOH log(n)). 
    104  */ 
    105     @property size_t length(); 
     171*/ 
     172    @property size_t length() 
     173    { 
     174        assert(0); 
     175    } 
    106176 
    107177/** 
    108178Returns the maximum number of elements the container can store without 
    109179(a) allocating memory, (b) invalidating iterators upon insertion. 
    110180 
    111181Complexity: $(BIGOH log(n)). 
    112182 */ 
    113     @property size_t capacity(); 
     183    @property size_t capacity() 
     184    { 
     185        assert(0); 
     186    } 
    114187 
    115188/** 
    116189Ensures sufficient capacity to accommodate $(D n) elements. 
    117190 
    118191Postcondition: $(D capacity >= n) 
    119192 
    120193Complexity: $(BIGOH log(e - capacity)) if $(D e > capacity), otherwise 
    121194$(BIGOH 1). 
    122195 */ 
    123     void reserve(size_t e); 
     196    void reserve(size_t e) 
     197    { 
     198        assert(0); 
     199    } 
    124200 
    125201/** 
    126202Returns a range that iterates over all elements of the container, in a 
    127203container-defined order. The container should choose the most 
    128204convenient and fast method of iteration for $(D opSlice()). 
    129205 
    130206Complexity: $(BIGOH log(n)) 
    131207 */ 
    132     Range opSlice(); 
     208    Range opSlice() 
     209    { 
     210        assert(0); 
     211    } 
     212 
     213    /** 
     214       Returns a range that iterates the container between two 
     215       specified positions. 
     216 
     217       Complexity: $(BIGOH log(n)) 
     218     */ 
     219    Range opSlice(size_t a, size_t b) 
     220    { 
     221        assert(0); 
     222    } 
    133223 
    134224/** 
    135225Forward to $(D opSlice().front) and $(D opSlice().back), respectively. 
    136226 
    137227Complexity: $(BIGOH log(n)) 
    138228 */ 
    139     @property ElementType front(); 
    140     /// ditto 
    141     @property ElementType back(); 
     229    @property T front() 
     230    { 
     231        assert(0); 
     232    } 
     233    /// Ditto 
     234    T moveFront() 
     235    { 
     236        assert(0); 
     237    } 
     238    /// Ditto 
     239    @property T back() 
     240    { 
     241        assert(0); 
     242    } 
     243    /// Ditto 
     244    T moveBack() 
     245    { 
     246        assert(0); 
     247    } 
    142248 
    143249/** 
    144250Indexing operators yield or modify the value at a specified index. 
    145251 */ 
    146     ValueType opIndex(KeyType); 
    147     /// ditto 
    148     void opIndexAssign(KeyType); 
    149     /// ditto 
    150     void opIndexOpAssign(string op)(KeyType); 
     252    /** 
     253       Indexing operators yield or modify the value at a specified index. 
     254     */ 
     255    ValueType opIndex(KeyType) 
     256    { 
     257        assert(0); 
     258    } 
     259    /// ditto 
     260    void opIndexAssign(KeyType) 
     261    { 
     262        assert(0); 
     263    } 
     264    /// ditto 
     265    void opIndexOpAssign(string op)(KeyType) 
     266    { 
     267        assert(0); 
     268    } 
     269    T moveAt(size_t i) 
     270    { 
     271        assert(0); 
     272    } 
    151273 
    152274/** 
    153275$(D k in container) returns true if the given key is in the container. 
    154276 */ 
    155     bool opBinary(string op)(KeyType k) if (op == "in"); 
     277    bool opBinary(string op)(KeyType k) if (op == "in") 
     278    { 
     279        assert(0); 
     280    } 
    156281 
    157282/** 
    158283Returns a range of all elements containing $(D k) (could be empty or a 
    159284singleton range). 
    160285 */ 
    161     Range equalRange(KeyType k); 
     286    Range equalRange(KeyType k) 
     287    { 
     288        assert(0); 
     289    } 
    162290 
    163291/** 
    164292Returns a range of all elements with keys less than $(D k) (could be 
    165293empty or a singleton range). Only defined by containers that store 
    166294data sorted at all times. 
    167295 */ 
    168     Range lowerBound(KeyType k); 
     296    Range lowerBound(KeyType k) 
     297    { 
     298        assert(0); 
     299    } 
    169300 
    170301/** 
    171302Returns a range of all elements with keys larger than $(D k) (could be 
    172303empty or a singleton range).  Only defined by containers that store 
    173304data sorted at all times. 
    174305 */ 
    175     Range upperBound(KeyType k); 
     306    Range upperBound(KeyType k) 
     307    { 
     308        assert(0); 
     309    } 
    176310 
    177311/** 
    178312Returns a new container that's the concatenation of $(D this) and its 
    179313argument. $(D opBinaryRight) is only defined if $(D Stuff) does not 
    180314define $(D opBinary). 
    181315 
    182316Complexity: $(BIGOH n + m), where m is the number of elements in $(D 
    183317stuff) 
    184318 */ 
    185     TotalContainer opBinary(string op)(Stuff rhs) if (op == "~"); 
    186  
    187     /// ditto 
    188     TotalContainer opBinaryRight(string op)(Stuff lhs) if (op == "~"); 
     319    TotalContainer opBinary(string op)(Stuff rhs) if (op == "~") 
     320    { 
     321        assert(0); 
     322    } 
     323 
     324    /// ditto 
     325    TotalContainer opBinaryRight(string op)(Stuff lhs) if (op == "~") 
     326    { 
     327        assert(0); 
     328    } 
    189329 
    190330/** 
    191331Forwards to $(D insertAfter(this[], stuff)). 
    192332 */ 
    193     void opOpAssign(string op)(Stuff stuff) if (op == "~"); 
     333    void opOpAssign(string op)(Stuff stuff) if (op == "~") 
     334    { 
     335        assert(0); 
     336    } 
    194337 
    195338/** 
    196339Removes all contents from the container. The container decides how $(D 
    197340capacity) is affected. 
    198341 
    199342Postcondition: $(D empty) 
    200343 
    201344Complexity: $(BIGOH n) 
    202345 */ 
    203     void clear(); 
     346    void clear() 
     347    { 
     348        assert(0); 
     349    } 
    204350 
    205351/** 
    206352Sets the number of elements in the container to $(D newSize). If $(D 
    207353newSize) is greater than $(D length), the added elements are added to 
    208354unspecified positions in the container and initialized with $(D 
    209 ElementType.init). 
     355.init). 
    210356 
    211357Complexity: $(BIGOH abs(n - newLength)) 
    212358 
    213 Postcondition: $(D length == newLength) 
    214  */ 
    215     @property void length(size_t newLength); 
     359Postcondition: $(D _length == newLength) 
     360 */ 
     361    @property void length(size_t newLength) 
     362    { 
     363        assert(0); 
     364    } 
    216365 
    217366/** 
    218367Inserts $(D stuff) in an unspecified position in the 
    219368container. Implementations should choose whichever insertion means is 
    220369the most advantageous for the container, but document the exact 
    221 behavior. $(D stuff) can be a value convertible to $(D ElementType) or 
    222 a range of objects convertible to $(D ElementType)
     370behavior. $(D stuff) can be a value convertible to the element type of 
     371the container, or a range of values convertible to it
    223372 
    224373The $(D stable) version guarantees that ranges iterating over the 
    225374container are never invalidated. Client code that counts on 
    226375non-invalidating insertion should use $(D stableInsert). Such code would 
    227376not compile against containers that don't support it. 
    228377 
    229378Returns: The number of elements added. 
    230379 
    231 Complexity: $(BIGOH m * log(n)), where m is the number of elements in 
    232 $(D stuff) 
    233  */ 
    234     size_t insert(Stuff stuff); 
     380Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
     381elements in $(D stuff) 
     382 */ 
     383    size_t insert(Stuff)(Stuff stuff) 
     384    { 
     385        assert(0); 
     386    } 
    235387    ///ditto 
    236     size_t stableInsert(Stuff stuff); 
     388    size_t stableInsert(Stuff)(Stuff stuff) 
     389    { 
     390        assert(0); 
     391    } 
     392 
     393/** 
     394Same as $(D insert(stuff)) and $(D stableInsert(stuff)) respectively, 
     395but relax the complexity constraint to linear. 
     396 */ 
     397    size_t linearInsert(Stuff)(Stuff stuff) 
     398    { 
     399        assert(0); 
     400    } 
     401    ///ditto 
     402    size_t stableLinearInsert(Stuff)(Stuff stuff) 
     403    { 
     404        assert(0); 
     405    } 
    237406 
    238407/** 
    239408Picks one value in an unspecified position in the container, removes 
    240409it from the container, and returns it. Implementations should pick the 
    241410value that's the most advantageous for the container, but document the 
    242411exact behavior. The stable version behaves the same, but guarantees that 
    243412ranges iterating over the container are never invalidated. 
    244413 
    245414Precondition: $(D !empty) 
    246415 
    247416Returns: The element removed. 
    248417 
    249418Complexity: $(BIGOH log(n)). 
    250419 */ 
    251     ElementType removeAny(); 
    252     /// ditto 
    253     ElementType stableRemoveAny(); 
     420    T removeAny() 
     421    { 
     422        assert(0); 
     423    } 
     424    /// ditto 
     425    T stableRemoveAny() 
     426    { 
     427        assert(0); 
     428    } 
    254429 
    255430/** 
    256431Inserts $(D value) to the front or back of the container. $(D stuff) 
    257 can be a value convertible to $(D ElementType) or a range of objects 
    258 convertible to $(D ElementType). The stable version behaves the same, 
    259 but guarantees that ranges iterating over the container are never 
     432can be a value convertible to the container's element type or a range 
     433of values convertible to it. The stable version behaves the same, but 
     434guarantees that ranges iterating over the container are never 
    260435invalidated. 
    261436 
    262437Returns: The number of elements inserted 
    263438 
    264439Complexity: $(BIGOH log(n)). 
    265440 */ 
    266     size_t insertFront(Stuff stuff); 
    267     /// ditto 
    268     size_t stableInsertFront(Stuff stuff); 
    269     /// ditto 
    270     size_t insertBack(Stuff stuff); 
    271     /// ditto 
    272     size_t stableInsertBack(T value); 
     441    size_t insertFront(Stuff)(Stuff stuff) 
     442    { 
     443        assert(0); 
     444    } 
     445    /// ditto 
     446    size_t stableInsertFront(Stuff)(Stuff stuff) 
     447    { 
     448        assert(0); 
     449    } 
     450    /// ditto 
     451    size_t insertBack(Stuff)(Stuff stuff) 
     452    { 
     453        assert(0); 
     454    } 
     455    /// ditto 
     456    size_t stableInsertBack(T value) 
     457    { 
     458        assert(0); 
     459    } 
    273460 
    274461/** 
    275462Removes the value at the front or back of the container. The stable 
    276463version behaves the same, but guarantees that ranges iterating over 
    277464the container are never invalidated. The optional parameter $(D 
    278465howMany) instructs removal of that many elements. If $(D howMany > n), 
    279466all elements are removed and no exception is thrown. 
    280467 
    281468Precondition: $(D !empty) 
    282469 
    283470Complexity: $(BIGOH log(n)). 
    284471 */ 
    285     void removeFront(); 
    286     /// ditto 
    287     void stableRemoveFront(); 
    288     /// ditto 
    289     void removeBack(); 
    290     /// ditto 
    291     void stableRemoveBack(); 
     472    void removeFront() 
     473    { 
     474        assert(0); 
     475    } 
     476    /// ditto 
     477    void stableRemoveFront() 
     478    { 
     479        assert(0); 
     480    } 
     481    /// ditto 
     482    void removeBack() 
     483    { 
     484        assert(0); 
     485    } 
     486    /// ditto 
     487    void stableRemoveBack() 
     488    { 
     489        assert(0); 
     490    } 
    292491 
    293492/** 
    294493Removes $(D howMany) values at the front or back of the 
    295494container. Unlike the unparameterized versions above, these functions 
    296495do not throw if they could not remove $(D howMany) elements. Instead, 
    297496if $(D howMany > n), all elements are removed. The returned value is 
    298497the effective number of elements removed. The stable version behaves 
    299498the same, but guarantees that ranges iterating over the container are 
    300499never invalidated. 
    301500 
    302501Returns: The number of elements removed 
    303502 
    304503Complexity: $(BIGOH howMany * log(n)). 
    305504 */ 
    306     size_t removeFront(size_t howMany); 
    307     /// ditto 
    308     size_t stableRemoveFront(size_t howMany); 
    309     /// ditto 
    310     size_t removeBack(size_t howMany); 
    311     /// ditto 
    312     size_t stableRemoveBack(size_t howMany); 
     505    size_t removeFront(size_t howMany) 
     506    { 
     507        assert(0); 
     508    } 
     509    /// ditto 
     510    size_t stableRemoveFront(size_t howMany) 
     511    { 
     512        assert(0); 
     513    } 
     514    /// ditto 
     515    size_t removeBack(size_t howMany) 
     516    { 
     517        assert(0); 
     518    } 
     519    /// ditto 
     520    size_t stableRemoveBack(size_t howMany) 
     521    { 
     522        assert(0); 
     523    } 
    313524 
    314525/** 
    315526Removes all values corresponding to key $(D k). 
    316527 
    317528Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
    318529elements with the same key. 
    319530 
    320531Returns: The number of elements removed. 
    321532 */ 
    322     size_t removeKey(KeyType k); 
     533    size_t removeKey(KeyType k) 
     534    { 
     535        assert(0); 
     536    } 
    323537 
    324538/** 
    325539Inserts $(D stuff) before, after, or instead range $(D r), which must 
    326540be a valid range previously extracted from this container. $(D stuff) 
    327 can be a value convertible to $(D ElementType) or a range of objects 
    328 convertible to $(D ElementType). The stable version behaves the same, 
    329 but guarantees that ranges iterating over the container are never 
     541can be a value convertible to the container's element type or a range 
     542of objects convertible to it. The stable version behaves the same, but 
     543guarantees that ranges iterating over the container are never 
    330544invalidated. 
    331545 
    332546Returns: The number of values inserted. 
    333547 
    334548Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) 
    335549 */ 
    336     size_t insertBefore(Range r, Stuff stuff); 
    337     /// ditto 
    338     size_t stableInsertBefore(Range r, Stuff stuff); 
    339     /// ditto 
    340     size_t insertAfter(Range r, Stuff stuff); 
    341     /// ditto 
    342     size_t stableInsertAfter(Range r, Stuff stuff); 
    343     /// ditto 
    344     size_t replace(Range r, Stuff stuff); 
    345     /// ditto 
    346     size_t stableReplace(Range r, Stuff stuff); 
     550    size_t insertBefore(Stuff)(Range r, Stuff stuff) 
     551    { 
     552        assert(0); 
     553    } 
     554    /// ditto 
     555    size_t stableInsertBefore(Stuff)(Range r, Stuff stuff) 
     556    { 
     557        assert(0); 
     558    } 
     559    /// ditto 
     560    size_t insertAfter(Stuff)(Range r, Stuff stuff) 
     561    { 
     562        assert(0); 
     563    } 
     564    /// ditto 
     565    size_t stableInsertAfter(Stuff)(Range r, Stuff stuff) 
     566    { 
     567        assert(0); 
     568    } 
     569    /// ditto 
     570    size_t replace(Stuff)(Range r, Stuff stuff) 
     571    { 
     572        assert(0); 
     573    } 
     574    /// ditto 
     575    size_t stableReplace(Stuff)(Range r, Stuff stuff) 
     576    { 
     577        assert(0); 
     578    } 
    347579 
    348580/** 
    349581Removes all elements belonging to $(D r), which must be a range 
    350582obtained originally from this container. The stable version behaves the 
    351583same, but guarantees that ranges iterating over the container are 
    352584never invalidated. 
    353585 
    354586Returns: A range spanning the remaining elements in the container that 
    355587initially were right after $(D r). 
    356588 
    357589Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
    358590elements in $(D r) 
    359591 */ 
    360     Range remove(Range r); 
    361     /// ditto 
    362     Range stableRemove(Range r); 
     592    Range remove(Range r) 
     593    { 
     594        assert(0); 
     595    } 
     596    /// ditto 
     597    Range stableRemove(Range r) 
     598    { 
     599        assert(0); 
     600    } 
    363601 
    364602/** 
    365603Same as $(D remove) above, but has complexity relaxed to linear. 
    366604 
    367605Returns: A range spanning the remaining elements in the container that 
    368606initially were right after $(D r). 
    369607 
    370608Complexity: $(BIGOH n) 
    371609 */ 
    372     Range linearRemove(Range r); 
    373     /// ditto 
    374     Range stableLinearRemove(Range r); 
     610    Range linearRemove(Range r) 
     611    { 
     612        assert(0); 
     613    } 
     614    /// ditto 
     615    Range stableLinearRemove(Range r) 
     616    { 
     617        assert(0); 
     618    } 
     619
     620 
     621unittest { 
     622    TotalContainer!int test; 
    375623} 
    376624 
    377625/** 
    378626Returns an initialized container. This function is mainly for 
    379627eliminating construction differences between $(D class) containers and 
    380628$(D struct) containers. 
    381629 */ 
    382630Container make(Container, T...)(T arguments) if (is(Container == struct)) 
    383631{ 
    384632    static if (T.length == 0) 
     
    601849 
    602850Complexity: $(BIGOH 1) 
    603851 */ 
    604852    void clear() 
    605853    { 
    606854        _root = null; 
    607855    } 
    608856 
    609857/** 
    610858Inserts $(D stuff) to the front of the container. $(D stuff) can be a 
    611 value convertible to $(D ElementType) or a range of objects 
    612 convertible to $(D ElementType). The stable version behaves the same, 
    613 but guarantees that ranges iterating over the container are never 
    614 invalidated. 
     859value convertible to $(D T) or a range of objects convertible to $(D 
     860T). The stable version behaves the same, but guarantees that ranges 
     861iterating over the container are never invalidated. 
    615862 
    616863Returns: The number of elements inserted 
    617864 
    618865Complexity: $(BIGOH log(n)) 
    619866 */ 
    620867    size_t insertFront(Stuff)(Stuff stuff) 
    621868    if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
    622869    { 
    623870        size_t result; 
    624871        Node * n, newRoot; 
     
    720967    alias removeFront stableRemoveFront; 
    721968 
    722969/** 
    723970Inserts $(D stuff) after range $(D r), which must be a range 
    724971previously extracted from this container. Given that all ranges for a 
    725972list end at the end of the list, this function essentially appends to 
    726973the list and uses $(D r) as a potentially fast way to reach the last 
    727974node in the list. (Ideally $(D r) is positioned near or at the last 
    728975element of the list.) 
    729976 
    730 $(D stuff) can be a value convertible to $(D ElementType) or a range 
    731 of objects convertible to $(D ElementType). The stable version behaves 
    732 the same, but guarantees that ranges iterating over the container are 
    733 never invalidated. 
     977$(D stuff) can be a value convertible to $(D T) or a range of objects 
     978convertible to $(D T). The stable version behaves the same, but 
     979guarantees that ranges iterating over the container are never 
     980invalidated. 
    734981 
    735982Returns: The number of values inserted. 
    736983 
    737984Complexity: $(BIGOH k + m), where $(D k) is the number of elements in 
    738985$(D r) and $(D m) is the length of $(D stuff). 
    739986 */ 
    740987 
    741988    size_t insertAfter(Stuff)(Range r, Stuff stuff) 
    742989    { 
    743990        if (!_root) 
     
    9701217 
    9711218    auto lst3 = lst ~ [ 7 ]; 
    9721219    assert(walkLength(lst3[]) == 5); 
    9731220} 
    9741221 
    9751222unittest 
    9761223{ 
    9771224    auto s = make!(SList!int)(1, 2, 3); 
    9781225} 
    9791226 
    980 version (none) 
    981 
    982 /** 
    983 _Array type with straightforward implementation building on $(D T[]). 
    984  */ 
    985 struct Array(T) 
    986 
    987     private struct Data 
     1227/** 
     1228Array type with deterministic control of memory. The memory allocated 
     1229for the array is reclaimed as soon as possible; there is no reliance 
     1230on the garbage collector. $(D Array) uses $(D malloc) and $(D free) 
     1231for managing its own memory. 
     1232 */ 
     1233struct Array(T) if (!is(T : const(bool))) 
     1234
     1235    // This structure is not copyable. 
     1236    private struct Payload 
    9881237    { 
    9891238        size_t _capacity; 
    9901239        T[] _payload; 
    991         this(size_t c, T[] p) { _capacity = c; _payload = p; } 
    992     } 
    993     private Data * _data; 
     1240 
     1241        // Convenience constructor 
     1242        this(T[] p) { _capacity = p.length; _payload = p; } 
     1243 
     1244        // Destructor releases array memory 
     1245        ~this() 
     1246        { 
     1247            foreach (ref e; _payload) .clear(e); 
     1248            static if (hasIndirections!T) 
     1249                GC.removeRange(_payload.ptr); 
     1250            free(_payload.ptr); 
     1251        } 
     1252 
     1253        this(this) 
     1254        { 
     1255            assert(0); 
     1256        } 
     1257 
     1258        void opAssign(Array!(T).Payload rhs) 
     1259        { 
     1260            assert(false); 
     1261        } 
     1262 
     1263        // Duplicate data 
     1264        // @property Payload dup() 
     1265        // { 
     1266        //     Payload result; 
     1267        //     result._payload = _payload.dup; 
     1268        //     // Conservatively assume initial capacity == length 
     1269        //     result._capacity = result._payload.length; 
     1270        //     return result; 
     1271        // } 
     1272 
     1273        // length 
     1274        @property size_t length() const 
     1275        { 
     1276            return _payload.length; 
     1277        } 
     1278 
     1279        // length 
     1280        @property void length(size_t newLength) 
     1281        { 
     1282            if (length >= newLength) 
     1283            { 
     1284                // shorten 
     1285                static if (is(T == struct) && hasElaborateDestructor!T) 
     1286                { 
     1287                    foreach (ref e; _payload.ptr[newLength .. _payload.length]) 
     1288                    { 
     1289                        clear(e); 
     1290                    } 
     1291                } 
     1292                _payload = _payload.ptr[0 .. newLength]; 
     1293                return; 
     1294            } 
     1295            // enlarge 
     1296            auto startEmplace = length; 
     1297            _payload = (cast(T*) realloc(_payload.ptr, 
     1298                            T.sizeof * newLength))[0 .. newLength]; 
     1299            initializeAll(_payload.ptr[startEmplace .. length]); 
     1300        } 
     1301 
     1302        // capacity 
     1303        @property size_t capacity() const 
     1304        { 
     1305            return _capacity; 
     1306        } 
     1307 
     1308        // reserve 
     1309        void reserve(size_t elements) 
     1310        { 
     1311            if (elements <= capacity) return; 
     1312            immutable sz = elements * T.sizeof; 
     1313            static if (hasIndirections!T)   // should use hasPointers instead 
     1314            { 
     1315                /* Because of the transactional nature of this 
     1316                 * relative to the garbage collector, ensure no 
     1317                 * threading bugs by using malloc/copy/free rather 
     1318                 * than realloc. 
     1319                 */ 
     1320                immutable oldLength = length; 
     1321                auto newPayload = 
     1322                    enforce((cast(T*) malloc(sz))[0 .. oldLength]); 
     1323                // copy old data over to new array 
     1324                newPayload[] = _payload[]; 
     1325                // Zero out unused capacity to prevent gc from seeing 
     1326                // false pointers 
     1327                memset(newPayload.ptr + oldLength, 
     1328                        0, 
     1329                        (elements - oldLength) * T.sizeof); 
     1330                GC.addRange(newPayload.ptr, sz); 
     1331                GC.removeRange(_data._payload.ptr); 
     1332                free(_data._payload.ptr); 
     1333                _data._payload = newPayload; 
     1334            } 
     1335            else 
     1336            { 
     1337                /* These can't have pointers, so no need to zero 
     1338                 * unused region 
     1339                 */ 
     1340                auto newPayload = 
     1341                    enforce(cast(T*) realloc(_payload.ptr, sz))[0 .. length]; 
     1342                _payload = newPayload; 
     1343            } 
     1344            _capacity = elements; 
     1345        } 
     1346 
     1347        // Insert one item 
     1348        size_t insertBack(Stuff)(Stuff stuff) 
     1349        if (isImplicitlyConvertible!(Stuff, T)) 
     1350        { 
     1351            if (_capacity == length) 
     1352            { 
     1353                reserve(1 + capacity * 3 / 2); 
     1354            } 
     1355            assert(capacity > length && _payload.ptr); 
     1356            emplace!T((cast(void*) (_payload.ptr + _payload.length)) 
     1357                    [0 .. T.sizeof], 
     1358                    stuff); 
     1359            _payload = _payload.ptr[0 .. _payload.length + 1]; 
     1360            return 1; 
     1361        } 
     1362 
     1363        /// Insert a range of items 
     1364        size_t insertBack(Stuff)(Stuff stuff) 
     1365        if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
     1366        { 
     1367            static if (hasLength!Stuff) 
     1368            { 
     1369                immutable oldLength = length; 
     1370                reserve(oldLength + stuff.length); 
     1371            } 
     1372            size_t result; 
     1373            foreach (item; stuff) 
     1374            { 
     1375                insertBack(item); 
     1376                ++result; 
     1377            } 
     1378            static if (hasLength!Stuff) 
     1379            { 
     1380                assert(length == oldLength + stuff.length); 
     1381            } 
     1382            return result; 
     1383        } 
     1384    } 
     1385    private alias RefCounted!(Payload, RefCountedAutoInitialize.no) Data; 
     1386    private Data _data; 
    9941387 
    9951388    this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) 
    9961389    { 
    997         _data = new Data(values.length, new T[values.length]); 
     1390        auto p = malloc(T.sizeof * values.length); 
     1391        if (hasIndirections!T && p) 
     1392        { 
     1393            GC.addRange(p, T.sizeof * values.length); 
     1394        } 
    9981395        foreach (i, e; values) 
    9991396        { 
    1000             _data._payload[i] = e; 
    1001         } 
     1397            emplace!T(p[i * T.sizeof .. (i + 1) * T.sizeof], e); 
     1398            assert((cast(T*) p)[i] == e); 
     1399        } 
     1400        _data.RefCounted.initialize((cast(T*) p)[0 .. values.length]); 
    10021401    } 
    10031402 
    10041403/** 
    10051404Comparison for equality. 
    10061405 */ 
    10071406    bool opEquals(ref const Array rhs) const 
    10081407    { 
    10091408        if (empty) return rhs.empty; 
    10101409        if (rhs.empty) return false; 
    10111410        return _data._payload == rhs._data._payload; 
    10121411    } 
    10131412 
    10141413/** 
    10151414Defines the container's primary range, which is a random-access range. 
    1016  */ 
    1017     alias T[] Range; 
     1415     */ 
     1416    struct Range 
     1417    { 
     1418        private Array _outer; 
     1419        private size_t _a, _b; 
     1420 
     1421        this(Array data, size_t a, size_t b) 
     1422        { 
     1423            _outer = data; 
     1424            _a = a; 
     1425            _b = b; 
     1426        } 
     1427 
     1428        @property bool empty() const 
     1429        { 
     1430            assert(_outer.length >= _b); 
     1431            return _a >= _b; 
     1432        } 
     1433 
     1434        @property Range save() 
     1435        { 
     1436            return this; 
     1437        } 
     1438 
     1439        @property T front() 
     1440        { 
     1441            enforce(!empty); 
     1442            return _outer[_a]; 
     1443        } 
     1444 
     1445        @property void front(T value) 
     1446        { 
     1447            enforce(!empty); 
     1448            _outer[_a] = move(value); 
     1449        } 
     1450 
     1451        void popFront() 
     1452        { 
     1453            enforce(!empty); 
     1454            ++_a; 
     1455        } 
     1456 
     1457        T moveFront() 
     1458        { 
     1459            enforce(!empty); 
     1460            return move(_outer._data._payload[_a]); 
     1461        } 
     1462 
     1463        T moveBack() 
     1464        { 
     1465            enforce(!empty); 
     1466            return move(_outer._data._payload[_b - 1]); 
     1467        } 
     1468 
     1469        T moveAt(size_t i) 
     1470        { 
     1471            i += _a; 
     1472            enforce(i < _b && !empty); 
     1473            return move(_outer._data._payload[_a + i]); 
     1474        } 
     1475 
     1476        T opIndex(size_t i) 
     1477        { 
     1478            i += _a; 
     1479            enforce(i < _b && _b <= _outer.length); 
     1480            return _outer[i]; 
     1481        } 
     1482 
     1483        void opIndexAssign(T value, size_t i) 
     1484        { 
     1485            i += _a; 
     1486            enforce(i < _b && _b <= _outer.length); 
     1487            _outer[i] = value; 
     1488        } 
     1489 
     1490        void opIndexOpAssign(string op)(T value, size_t i) 
     1491        { 
     1492            enforce(_outer && _a + i < _b && _b <= _outer._payload.length); 
     1493            mixin("_outer._payload.ptr[_a + i] "~op~"= value;"); 
     1494        } 
     1495    } 
    10181496 
    10191497/** 
    10201498Property returning $(D true) if and only if the container has no 
    10211499elements. 
    10221500 
    10231501Complexity: $(BIGOH 1) 
    10241502 */ 
    10251503    @property bool empty() const 
    10261504    { 
    1027         return !_data || _data._payload.empty; 
     1505        return !_data.RefCounted.isInitialized || _data._payload.empty; 
    10281506    } 
    10291507 
    10301508/** 
    10311509Duplicates the container. The elements themselves are not transitively 
    10321510duplicated. 
    10331511 
    10341512Complexity: $(BIGOH n). 
    10351513 */ 
    10361514    @property Array dup() 
    10371515    { 
    1038         if (!_data) return this; 
    1039         Array result; 
    1040         result._data = new Data(_data._capacity, _data._payload.dup); 
    1041         return result; 
     1516        if (!_data.RefCounted.isInitialized) return this; 
     1517        return Array(_data._payload); 
    10421518    } 
    10431519 
    10441520/** 
    10451521Returns the number of elements in the container. 
    10461522 
    10471523Complexity: $(BIGOH 1). 
    10481524 */ 
    10491525    @property size_t length() const 
    10501526    { 
    1051         return _data ? _data._payload.length : 0; 
     1527        return _data.RefCounted.isInitialized ? _data._payload.length : 0; 
    10521528    } 
    10531529 
    10541530/** 
    10551531Returns the maximum number of elements the container can store without 
    10561532   (a) allocating memory, (b) invalidating iterators upon insertion. 
    10571533 
    10581534Complexity: $(BIGOH 1) 
    10591535 */ 
    10601536    @property size_t capacity() 
    10611537    { 
    1062         return _data ? _data._capacity : 0; 
     1538        return _data.RefCounted.isInitialized ? _data._capacity : 0; 
    10631539    } 
    10641540 
    10651541/** 
    10661542Ensures sufficient capacity to accommodate $(D e) elements. 
    10671543 
    10681544Postcondition: $(D capacity >= e) 
    10691545 
    10701546Complexity: $(BIGOH 1) 
    1071  */ 
    1072     void reserve(size_t e) 
    1073     { 
    1074         if (!_data) 
    1075         { 
    1076             auto newPayload = (cast(T*) core.memory.GC.malloc( 
    1077                         e * T.sizeof))[0 .. 0]; 
    1078             _data = new Data(e, newPayload); 
     1547     */ 
     1548    void reserve(size_t elements) 
     1549    { 
     1550        if (!_data.RefCounted.isInitialized) 
     1551        { 
     1552            if (!elements) return; 
     1553            immutable sz = elements * T.sizeof; 
     1554            auto p = enforce(malloc(sz)); 
     1555            static if (hasIndirections!T) 
     1556            { 
     1557                GC.addRange(p, sz); 
     1558            } 
     1559            _data.RefCounted.initialize(cast(T[]) p[0 .. 0]); 
     1560            _data._capacity = elements; 
    10791561        } 
    10801562        else 
    10811563        { 
    1082             if (e <= _data._capacity) return; 
    1083             auto newPayload = (cast(T*) core.memory.GC.realloc( 
    1084                         _data._payload.ptr, 
    1085                         e * T.sizeof))[0 .. _data._payload.length]; 
    1086             _data._payload = newPayload; 
    1087             _data._capacity = e; 
     1564            _data.reserve(elements); 
    10881565        } 
    10891566    } 
    10901567 
    10911568/** 
    10921569Returns a range that iterates over elements of the container, in 
    10931570forward order. 
    10941571 
    10951572Complexity: $(BIGOH 1) 
    10961573 */ 
    10971574    Range opSlice() 
    10981575    { 
    1099         return _data ? _data._payload : null; 
     1576        // Workaround for bug 4356 
     1577        Array copy; 
     1578        copy._data = this._data; 
     1579        return Range(copy, 0, length); 
    11001580    } 
    11011581 
    11021582/** 
    11031583Returns a range that iterates over elements of the container from 
    11041584index $(D a) up to (excluding) index $(D b). 
    11051585 
    11061586Precondition: $(D a <= b && b <= length) 
    11071587 
    11081588Complexity: $(BIGOH 1) 
    11091589 */ 
    11101590    Range opSlice(size_t a, size_t b) 
    11111591    { 
    11121592        enforce(a <= b && b <= length); 
    1113         return _data ? _data._payload[a .. b] : (enforce(b == 0), (T[]).init); 
     1593        // Workaround for bug 4356 
     1594        Array copy; 
     1595        copy._data = this._data; 
     1596        return Range(copy, a, b); 
    11141597    } 
    11151598 
    11161599/** 
    11171600@@@BUG@@@ This doesn't work yet 
    11181601 */ 
    11191602    size_t opDollar() const 
    11201603    { 
    11211604        return length; 
    11221605    } 
    11231606 
     
    11571640 
    11581641/** 
    11591642Indexing operators yield or modify the value at a specified index. 
    11601643 
    11611644Precondition: $(D i < length) 
    11621645 
    11631646Complexity: $(BIGOH 1) 
    11641647 */ 
    11651648    T opIndex(size_t i) 
    11661649    { 
    1167         enforce(_data); 
     1650        enforce(_data.RefCounted.isInitialized); 
    11681651        return _data._payload[i]; 
    11691652    } 
    11701653 
    11711654    /// ditto 
    11721655    void opIndexAssign(T value, size_t i) 
    11731656    { 
    1174         enforce(_data); 
     1657        enforce(_data.RefCounted.isInitialized); 
    11751658        _data._payload[i] = value; 
    11761659    } 
    11771660 
    11781661/// ditto 
    11791662    void opIndexOpAssign(string op)(T value, size_t i) 
    11801663    { 
    11811664        mixin("_data._payload[i] "~op~"= value;"); 
    11821665    } 
    11831666 
    11841667/** 
    11851668Returns a new container that's the concatenation of $(D this) and its 
    11861669argument. $(D opBinaryRight) is only defined if $(D Stuff) does not 
    11871670define $(D opBinary). 
    11881671 
    11891672Complexity: $(BIGOH n + m), where m is the number of elements in $(D 
    11901673stuff) 
    11911674 */ 
    11921675    Array opBinary(string op, Stuff)(Stuff stuff) if (op == "~") 
    11931676    { 
    11941677        // TODO: optimize 
    1195         auto result = Array(this[]); 
    1196         result ~= stuff; 
     1678        Array result; 
     1679        // @@@BUG@@ result ~= this[] doesn't work 
     1680        auto r = this[]; 
     1681        result ~= r; 
     1682        assert(result.length == length); 
     1683        result ~= stuff[]; 
    11971684        return result; 
    11981685    } 
    11991686 
    12001687/** 
    12011688Forwards to $(D insertBack(stuff)). 
    12021689 */ 
    12031690    void opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") 
    12041691    { 
    12051692        static if (is(typeof(stuff[]))) 
    12061693        { 
     
    12151702/** 
    12161703Removes all contents from the container. The container decides how $(D 
    12171704capacity) is affected. 
    12181705 
    12191706Postcondition: $(D empty) 
    12201707 
    12211708Complexity: $(BIGOH n) 
    12221709 */ 
    12231710    void clear() 
    12241711    { 
    1225         _data = null
     1712        .clear(_data)
    12261713    } 
    12271714 
    12281715/** 
    12291716Sets the number of elements in the container to $(D newSize). If $(D 
    12301717newSize) is greater than $(D length), the added elements are added to 
    12311718unspecified positions in the container and initialized with $(D 
    1232 ElementType.init). 
     1719T.init). 
    12331720 
    12341721Complexity: $(BIGOH abs(n - newLength)) 
    12351722 
    12361723Postcondition: $(D length == newLength) 
    12371724 */ 
    12381725    @property void length(size_t newLength) 
    12391726    { 
    1240         if (!_data) 
    1241         { 
    1242             _data = new Data(newLength, new T[newLength]); 
    1243         } 
    1244         else 
    1245         { 
    1246             _data._payload.length = newLength; 
    1247             if (newLength > capacity) 
    1248             { 
    1249                 _data._capacity = newLength; 
    1250             } 
    1251         } 
     1727        _data.RefCounted.ensureInitialized(); 
     1728        _data.length = newLength; 
    12521729    } 
    12531730 
    12541731/** 
    12551732Picks one value in an unspecified position in the container, removes 
    12561733it from the container, and returns it. Implementations should pick the 
    12571734value that's the most advantageous for the container, but document the 
    12581735exact behavior. The stable version behaves the same, but guarantees 
    12591736that ranges iterating over the container are never invalidated. 
    12601737 
    12611738Precondition: $(D !empty) 
     
    12681745    { 
    12691746        auto result = back; 
    12701747        removeBack(); 
    12711748        return result; 
    12721749    } 
    12731750    /// ditto 
    12741751    alias removeAny stableRemoveAny; 
    12751752 
    12761753/** 
    12771754Inserts $(D value) to the front or back of the container. $(D stuff) 
    1278 can be a value convertible to $(D ElementType) or a range of objects 
    1279 convertible to $(D ElementType). The stable version behaves the same, 
    1280 but guarantees that ranges iterating over the container are never 
    1281 invalidated. 
     1755can be a value convertible to $(D T) or a range of objects convertible 
     1756to $(D T). The stable version behaves the same, but guarantees that 
     1757ranges iterating over the container are never invalidated. 
    12821758 
    12831759Returns: The number of elements inserted 
    12841760 
    12851761Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
    12861762elements in $(D stuff) 
    12871763 */ 
    12881764    size_t insertBack(Stuff)(Stuff stuff) 
    1289     if (isImplicitlyConvertible!(Stuff, T)) 
    1290     { 
    1291         if (capacity == length) 
    1292         { 
    1293             reserve(1 + capacity * 3 / 2); 
    1294         } 
    1295         _data._payload = _data._payload.ptr[0 .. _data._payload.length + 1]; 
    1296         _data._payload[$ - 1] = stuff; 
    1297         return 1; 
    1298     } 
    1299  
    1300 /// ditto 
    1301     size_t insertBack(Stuff)(Stuff stuff) 
    1302     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
    1303     { 
    1304         size_t result; 
    1305         foreach (item; stuff) 
    1306         { 
    1307             insertBack(item); 
    1308             ++result; 
    1309         } 
    1310         return result; 
     1765    if (isImplicitlyConvertible!(Stuff, T) || 
     1766            isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
     1767    { 
     1768        _data.RefCounted.ensureInitialized(); 
     1769        return _data.insertBack(stuff); 
    13111770    } 
    13121771/// ditto 
    13131772    alias insertBack insert; 
    13141773 
    13151774/** 
    13161775Removes the value at the back of the container. The stable version 
    13171776behaves the same, but guarantees that ranges iterating over the 
    13181777container are never invalidated. 
    13191778 
    13201779Precondition: $(D !empty) 
    13211780 
    13221781Complexity: $(BIGOH log(n)). 
    13231782 */ 
    13241783    void removeBack() 
    13251784    { 
    13261785        enforce(!empty); 
     1786        static if (is(T == struct)) 
     1787        { 
     1788            // Destroy this guy 
     1789            clear(_data._payload[$ - 1]); 
     1790        } 
    13271791        _data._payload = _data._payload[0 .. $ - 1]; 
    13281792    } 
    13291793/// ditto 
    13301794    alias removeBack stableRemoveBack; 
    13311795 
    13321796/** 
    13331797Removes $(D howMany) values at the front or back of the 
    13341798container. Unlike the unparameterized versions above, these functions 
    13351799do not throw if they could not remove $(D howMany) elements. Instead, 
    13361800if $(D howMany > n), all elements are removed. The returned value is 
     
    13381802the same, but guarantees that ranges iterating over the container are 
    13391803never invalidated. 
    13401804 
    13411805Returns: The number of elements removed 
    13421806 
    13431807Complexity: $(BIGOH howMany). 
    13441808 */ 
    13451809    size_t removeBack(size_t howMany) 
    13461810    { 
    13471811        if (howMany > length) howMany = length; 
     1812        static if (is(T == struct)) 
     1813        { 
     1814            // Destroy this guy 
     1815            foreach (ref e; _data._payload[$ - howMany .. $]) 
     1816            { 
     1817                clear(e); 
     1818            } 
     1819        } 
    13481820        _data._payload = _data._payload[0 .. $ - howMany]; 
    13491821        return howMany; 
    13501822    } 
    13511823    /// ditto 
    13521824    alias removeBack stableRemoveBack; 
    13531825 
    13541826/** 
    13551827Inserts $(D stuff) before, after, or instead range $(D r), which must 
    13561828be a valid range previously extracted from this container. $(D stuff) 
    1357 can be a value convertible to $(D ElementType) or a range of objects 
    1358 convertible to $(D ElementType). The stable version behaves the same, 
    1359 but guarantees that ranges iterating over the container are never 
    1360 invalidated. 
     1829can be a value convertible to $(D T) or a range of objects convertible 
     1830to $(D T). The stable version behaves the same, but guarantees that 
     1831ranges iterating over the container are never invalidated. 
    13611832 
    13621833Returns: The number of values inserted. 
    13631834 
    13641835Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) 
    1365  */ 
    1366     size_t insertBefore(Stuff)(Range r, Stuff stuff) 
    1367     { 
    1368         // TODO: optimize 
    1369         enforce(_data); 
    1370         immutable offset = r.ptr - _data._payload.ptr; 
    1371         enforce(offset <= length); 
    1372         auto result = insertBack(stuff); 
    1373         bringToFront(this[offset .. length - result], 
    1374                 this[length - result .. length]); 
    1375         return result; 
    1376     } 
    1377  
    1378     /// ditto 
    1379     size_t insertAfter(Stuff)(Range r, Stuff stuff) 
    1380     { 
    1381         // TODO: optimize 
    1382         enforce(_data); 
    1383         immutable offset = r.ptr + r.length - _data._payload.ptr; 
    1384         enforce(offset <= length); 
    1385         auto result = insertBack(stuff); 
    1386         bringToFront(this[offset .. length - result], 
    1387                 this[length - result .. length]); 
    1388         return result; 
    1389     } 
    1390  
    1391 /// ditto 
    1392     size_t replace(Stuff)(Range r, Stuff stuff) 
    1393     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
    1394     { 
    1395         enforce(_data); 
    1396         immutable offset = r.ptr - _data._payload.ptr; 
    1397         enforce(offset <= length); 
    1398         size_t result; 
    1399         for (; !stuff.empty; stuff.popFront()) 
    1400         { 
    1401             if (r.empty) 
    1402             { 
    1403                 // append the rest 
    1404                 return result + insertBack(stuff); 
    1405             } 
    1406             r.front = stuff.front; 
    1407             r.popFront(); 
    1408             ++result; 
    1409         } 
    1410         // Remove remaining stuff in r 
    1411         remove(r); 
    1412         return result; 
    1413     } 
    1414  
    1415 /// ditto 
    1416     size_t replace(Stuff)(Range r, Stuff stuff) 
    1417     if (isImplicitlyConvertible!(Stuff, T)) 
    1418     { 
    1419         if (r.empty) 
    1420         { 
    1421             insertBefore(r, stuff); 
    1422         } 
    1423         else 
    1424         { 
    1425             r.front = stuff; 
    1426             r.popFront(); 
    1427             remove(r); 
    1428         } 
    1429         return 1; 
    1430     } 
    1431  
    1432 /** 
    1433 Removes all elements belonging to $(D r), which must be a range 
    1434 obtained originally from this container. The stable version behaves 
    1435 the same, but guarantees that ranges iterating over the container are 
    1436 never invalidated. 
    1437  
    1438 Returns: A range spanning the remaining elements in the container that 
    1439 initially were right after $(D r). 
    1440  
    1441 Complexity: $(BIGOH n - m), where $(D m) is the number of elements in 
    1442 $(D r) 
    1443  */ 
    1444     Range linearRemove(Range r) 
    1445     { 
    1446         enforce(_data); 
    1447         immutable offset1 = r.ptr - _data._payload.ptr; 
    1448         immutable offset2 = offset1 + r.length; 
    1449         enforce(offset1 <= offset2 && offset2 <= length); 
    1450         immutable tailLength = length - offset2; 
    1451         // Use copy here, not a[] = b[] because the ranges may overlap 
    1452         copy(this[offset2 .. length], this[offset1 .. offset1 + tailLength]); 
    1453         length = offset1 + tailLength; 
    1454         return this[length - tailLength .. length]; 
    1455     } 
    1456  
    1457     /// ditto 
    1458     alias remove stableLinearRemove; 
    1459  
    1460 
    1461  
    1462 unittest 
    1463 
    1464     Array!int a; 
    1465     assert(a.empty); 
    1466 
    1467  
    1468 unittest 
    1469 
    1470     auto a = Array!int(1, 2, 3); 
    1471     auto b = a.dup; 
    1472     assert(b == Array!int(1, 2, 3)); 
    1473     b.front = 42; 
    1474     assert(b == Array!int(42, 2, 3)); 
    1475     assert(a == Array!int(1, 2, 3)); 
    1476 
    1477  
    1478 unittest 
    1479 
    1480     auto a = Array!int(1, 2, 3); 
    1481     assert(a.length == 3); 
    1482 
    1483  
    1484 unittest 
    1485 
    1486     Array!int a; 
    1487     a.reserve(1000); 
    1488     assert(a.length == 0); 
    1489     assert(a.empty); 
    1490     assert(a.capacity >= 1000); 
    1491     auto p = a._data._payload.ptr; 
    1492     foreach (i; 0 .. 1000) 
    1493     { 
    1494         a.insertBack(i); 
    1495     } 
    1496     assert(p == a._data._payload.ptr); 
    1497 
    1498  
    1499 unittest 
    1500 
    1501     auto a = Array!int(1, 2, 3); 
    1502     a[1] *= 42; 
    1503     assert(a[1] == 84); 
    1504 
    1505  
    1506 unittest 
    1507 
    1508     auto a = Array!int(1, 2, 3); 
    1509     auto b = Array!int(11, 12, 13); 
    1510     assert(a ~ b == Array!int(1, 2, 3, 11, 12, 13)); 
    1511     assert(a ~ b[] == Array!int(1, 2, 3, 11, 12, 13)); 
    1512 
    1513  
    1514 unittest 
    1515 
    1516     auto a = Array!int(1, 2, 3); 
    1517     auto b = Array!int(11, 12, 13); 
    1518     a ~= b; 
    1519     assert(a == Array!int(1, 2, 3, 11, 12, 13)); 
    1520 
    1521  
    1522 unittest 
    1523 
    1524     auto a = Array!int(1, 2, 3, 4); 
    1525     assert(a.removeAny() == 4); 
    1526     assert(a == Array!int(1, 2, 3)); 
    1527 
    1528  
    1529 unittest 
    1530 
    1531     auto a = Array!int(1, 2, 3, 4, 5); 
    1532     auto r = a[2 .. a.length]; 
    1533     assert(a.insertBefore(r, 42) == 1); 
    1534     assert(a == Array!int(1, 2, 42, 3, 4, 5)); 
    1535     r = a[2 .. 2]; 
    1536     assert(a.insertBefore(r, [8, 9]) == 2); 
    1537     assert(a == Array!int(1, 2, 8, 9, 42, 3, 4, 5)); 
    1538 
    1539  
    1540 unittest 
    1541 
    1542     auto a = Array!int(0, 1, 2, 3, 4, 5, 6, 7, 8); 
    1543     a.linearRemove(a[4 .. 6]); 
    1544     assert(a == Array!int(0, 1, 2, 3, 6, 7, 8)); 
    1545 
    1546 
    1547  
    1548 /** 
    1549 Array type with deterministic control of memory. The memory allocated 
    1550 for the array is reclaimed as soon as possible; there is no reliance 
    1551 on the garbage collector. 
    1552  */ 
    1553 struct Array(T) 
    1554 
    1555     private struct Data 
    1556     { 
    1557         uint _refCount = 1; 
    1558         size_t _capacity; 
    1559         T[] _payload; 
    1560         this(T[] p) { _capacity = p.length; _payload = p; } 
    1561     } 
    1562     private Data * _data; 
    1563  
    1564     this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) 
    1565     { 
    1566     auto p = malloc(T.sizeof * values.length); 
    1567     if (T.sizeof >= size_t.sizeof && p) 
    1568         GC.addRange(p, T.sizeof * values.length); 
    1569         _data = emplace!Data( 
    1570             malloc(Data.sizeof)[0 .. Data.sizeof], 
    1571             (cast(T*) p)[0 .. values.length]); 
    1572         assert(_data._refCount == 1); 
    1573         foreach (i, e; values) 
    1574         { 
    1575             emplace!T((cast(void*) &_data._payload[i])[0 .. T.sizeof], e); 
    1576             assert(_data._payload[i] == e); 
    1577         } 
    1578     } 
    1579  
    1580     this(this) 
    1581     { 
    1582         if (_data) 
    1583         { 
    1584             ++_data._refCount; 
    1585         } 
    1586     } 
    1587  
    1588     ~this() 
    1589     { 
    1590         if (!_data) return; 
    1591         if (_data._refCount > 1) 
    1592         { 
    1593             --_data._refCount; 
    1594             return; 
    1595         } 
    1596         assert(_data._refCount == 1); 
    1597         --_data._refCount; 
    1598         foreach (ref e; _data._payload) .clear(e); 
    1599     if (T.sizeof >= size_t.sizeof) 
    1600         GC.removeRange(_data._payload.ptr); 
    1601         free(_data._payload.ptr); 
    1602         free(_data); 
    1603         _data = null; 
    1604     } 
    1605  
    1606     void opAssign(Array another) 
    1607     { 
    1608         swap(this, another); 
    1609     } 
    1610  
    1611 /** 
    1612 Comparison for equality. 
    1613  */ 
    1614     bool opEquals(ref const Array rhs) const 
    1615     { 
    1616         if (empty) return rhs.empty; 
    1617         if (rhs.empty) return false; 
    1618         return _data._payload == rhs._data._payload; 
    1619     } 
    1620  
    1621 /** 
    1622 Defines the container's primary range, which is a random-access range. 
    1623  */ 
    1624     struct Range 
    1625     { 
    1626         private Data * _data; 
    1627         private size_t _a, _b; 
    1628  
    1629         private this(Data * data, size_t a, size_t b) 
    1630         { 
    1631             _data = data; 
    1632             if (!_data) 
    1633             { 
    1634                 assert(a == 0 && b == 0); 
    1635                 return; 
    1636             } 
    1637             ++_data._refCount; 
    1638             _a = a; 
    1639             _b = b; 
    1640         } 
    1641  
    1642         this(this) 
    1643         { 
    1644             if (_data) 
    1645             { 
    1646                 ++_data._refCount; 
    1647             } 
    1648         } 
    1649  
    1650         ~this() 
    1651         { 
    1652             if (!_data) return; 
    1653             if (_data._refCount > 1) 
    1654             { 
    1655                 --_data._refCount; 
    1656                 return; 
    1657             } 
    1658             assert(_data._refCount == 1); 
    1659             foreach (ref e; _data._payload) .clear(e); 
    1660             free(_data._payload.ptr); 
    1661             free(_data); 
    1662             _data = null; 
    1663             _a = _b = 0; 
    1664         } 
    1665  
    1666         void opAssign(Range another) 
    1667         { 
    1668             swap(this, another); 
    1669         } 
    1670  
    1671         @property bool empty() const 
    1672         { 
    1673             return !_data || _a == _b || _data._payload.length <= _a; 
    1674         } 
    1675  
    1676         @property Range save() 
    1677         { 
    1678             return this; 
    1679         } 
    1680  
    1681         @property T front() 
    1682         { 
    1683             enforce(_data && _a < _data._payload.length); 
    1684             return _data._payload[_a]; 
    1685         } 
    1686  
    1687         void popFront() 
    1688         { 
    1689             enforce(!empty); 
    1690             ++_a; 
    1691         } 
    1692  
    1693         void put(T e) 
    1694         { 
    1695             enforce(!empty); 
    1696             _data._payload[_a] = e; 
    1697             popFront(); 
    1698         } 
    1699  
    1700         T moveFront() 
    1701         { 
    1702             enforce(_data && _a < _data._payload.length); 
    1703             return move(_data._payload[_a]); 
    1704         } 
    1705  
    1706         T moveBack() 
    1707         { 
    1708             enforce(_data && _b <= _data._payload.length); 
    1709             return move(_data._payload[_b - 1]); 
    1710         } 
    1711  
    1712         T moveAt(size_t i) 
    1713         { 
    1714             enforce(_data && _a + i < _b && _b <= _data._payload.length); 
    1715             return move(_data._payload[_a + i]); 
    1716         } 
    1717  
    1718         T opIndex(size_t i) 
    1719         { 
    1720             enforce(_data && _a + i < _b && _b <= _data._payload.length); 
    1721             return _data._payload.ptr[_a + i]; 
    1722         } 
    1723  
    1724         void opIndexAssign(T value, size_t i) 
    1725         { 
    1726             enforce(_data && _a + i < _b && _b <= _data._payload.length); 
    1727             swap(_data._payload.ptr[_a + i], value); 
    1728         } 
    1729  
    1730         void opIndexOpAssign(string op)(T value, size_t i) 
    1731         { 
    1732             enforce(_data && _a + i < _b && _b <= _data._payload.length); 
    1733             mixin("_data._payload.ptr[_a + i] "~op~"= value;"); 
    1734         } 
    1735     } 
    1736  
    1737 /** 
    1738 Property returning $(D true) if and only if the container has no 
    1739 elements. 
    1740  
    1741 Complexity: $(BIGOH 1) 
    1742  */ 
    1743     @property bool empty() const 
    1744     { 
    1745         return !_data || _data._payload.empty; 
    1746     } 
    1747  
    1748 /** 
    1749 Duplicates the container. The elements themselves are not transitively 
    1750 duplicated. 
    1751  
    1752 Complexity: $(BIGOH n). 
    1753  */ 
    1754     @property Array dup() 
    1755     { 
    1756         if (!_data) return this; 
    1757         return Array(_data._payload); 
    1758     } 
    1759  
    1760 /** 
    1761 Returns the number of elements in the container. 
    1762  
    1763 Complexity: $(BIGOH 1). 
    1764  */ 
    1765     @property size_t length() const 
    1766     { 
    1767         return _data ? _data._payload.length : 0; 
    1768     } 
    1769  
    1770 /** 
    1771 Returns the maximum number of elements the container can store without 
    1772    (a) allocating memory, (b) invalidating iterators upon insertion. 
    1773  
    1774 Complexity: $(BIGOH 1) 
    1775  */ 
    1776     @property size_t capacity() 
    1777     { 
    1778         return _data ? _data._capacity : 0; 
    1779     } 
    1780  
    1781 /** 
    1782 Ensures sufficient capacity to accommodate $(D e) elements. 
    1783  
    1784 Postcondition: $(D capacity >= e) 
    1785  
    1786 Complexity: $(BIGOH 1) 
    1787  */ 
    1788     void reserve(size_t elements) 
    1789     { 
    1790         if (!_data) 
    1791         { 
    1792         auto p = malloc(elements * T.sizeof); 
    1793         if (T.sizeof >= size_t.sizeof && p) // should use hasPointers instead 
    1794         GC.addRange(p, T.sizeof * elements); 
    1795             _data = emplace!Data(malloc(Data.sizeof)[0 .. Data.sizeof], 
    1796                     (cast(T*) p)[0 .. 0]); 
    1797             _data._capacity = elements; 
    1798         } 
    1799         else 
    1800         { 
    1801             if (elements <= _data._capacity) return; 
    1802  
    1803         auto sz = elements * T.sizeof; 
    1804         if (T.sizeof >= size_t.sizeof)  // should use hasPointers instead 
    1805         { 
    1806         /* Because of the transactional nature of this relative to the 
    1807          * garbage collector, ensure no threading bugs by using malloc/copy/free 
    1808          * rather than realloc. 
    1809          */ 
    1810         auto newPayload = (cast(T*) malloc(sz))[0 .. _data._payload.length]; 
    1811         newPayload || assert(false); 
    1812         newPayload[] = _data._payload[];    // copy old data over to new array 
    1813         // Zero out unused capacity to prevent gc from seeing false pointers 
    1814         memset(newPayload.ptr + _data._payload.length, 
    1815                0, 
    1816                (elements - _data._payload.length) * T.sizeof); 
    1817         GC.addRange(newPayload.ptr, sz); 
    1818         GC.removeRange(_data._payload.ptr); 
    1819         free(_data._payload.ptr); 
    1820         _data._payload = newPayload; 
    1821         } 
    1822         else 
    1823         { 
    1824         /* These can't have pointers, so no need to zero unused region 
    1825          */ 
    1826         auto newPayload = (cast(T*) realloc(_data._payload.ptr, sz)) 
    1827             [0 .. _data._payload.length]; 
    1828         newPayload || assert(false); 
    1829         _data._payload = newPayload; 
    1830         } 
    1831             _data._capacity = elements; 
    1832         } 
    1833     } 
    1834  
    1835 /** 
    1836 Returns a range that iterates over elements of the container, in 
    1837 forward order. 
    1838  
    1839 Complexity: $(BIGOH 1) 
    1840  */ 
    1841     Range opSlice() 
    1842     { 
    1843         return Range(_data, 0, length); 
    1844     } 
    1845  
    1846 /** 
    1847 Returns a range that iterates over elements of the container from 
    1848 index $(D a) up to (excluding) index $(D b). 
    1849  
    1850 Precondition: $(D a <= b && b <= length) 
    1851  
    1852 Complexity: $(BIGOH 1) 
    1853  */ 
    1854     Range opSlice(size_t a, size_t b) 
    1855     { 
    1856         enforce(a <= b && b <= length); 
    1857         return Range(_data, a, b); 
    1858     } 
    1859  
    1860 /** 
    1861 @@@BUG@@@ This doesn't work yet 
    1862  */ 
    1863     size_t opDollar() const 
    1864     { 
    1865         return length; 
    1866     } 
    1867  
    1868 /** 
    1869 Forward to $(D opSlice().front) and $(D opSlice().back), respectively. 
    1870  
    1871 Precondition: $(D !empty) 
    1872  
    1873 Complexity: $(BIGOH 1) 
    1874  */ 
    1875     @property T front() 
    1876     { 
    1877         enforce(!empty); 
    1878         return *_data._payload.ptr; 
    1879     } 
    1880  
    1881 /// ditto 
    1882     @property void front(T value) 
    1883     { 
    1884         enforce(!empty); 
    1885         *_data._payload.ptr = value; 
    1886     } 
    1887  
    1888 /// ditto 
    1889     @property T back() 
    1890     { 
    1891         enforce(!empty); 
    1892         return _data._payload[$ - 1]; 
    1893     } 
    1894  
    1895 /// ditto 
    1896     @property void back(T value) 
    1897     { 
    1898         enforce(!empty); 
    1899         _data._payload[$ - 1] = value; 
    1900     } 
    1901  
    1902 /** 
    1903 Indexing operators yield or modify the value at a specified index. 
    1904  
    1905 Precondition: $(D i < length) 
    1906  
    1907 Complexity: $(BIGOH 1) 
    1908  */ 
    1909     T opIndex(size_t i) 
    1910     { 
    1911         enforce(_data); 
    1912         return _data._payload[i]; 
    1913     } 
    1914  
    1915     /// ditto 
    1916     void opIndexAssign(T value, size_t i) 
    1917     { 
    1918         enforce(_data); 
    1919         _data._payload[i] = value; 
    1920     } 
    1921  
    1922 /// ditto 
    1923     void opIndexOpAssign(string op)(T value, size_t i) 
    1924     { 
    1925         mixin("_data._payload[i] "~op~"= value;"); 
    1926     } 
    1927  
    1928 /** 
    1929 Returns a new container that's the concatenation of $(D this) and its 
    1930 argument. $(D opBinaryRight) is only defined if $(D Stuff) does not 
    1931 define $(D opBinary). 
    1932  
    1933 Complexity: $(BIGOH n + m), where m is the number of elements in $(D 
    1934 stuff) 
    1935  */ 
    1936     Array opBinary(string op, Stuff)(Stuff stuff) if (op == "~") 
    1937     { 
    1938         // TODO: optimize 
    1939         Array result; 
    1940         result ~= this[]; 
    1941         result ~= stuff; 
    1942         return result; 
    1943     } 
    1944  
    1945 /** 
    1946 Forwards to $(D insertBack(stuff)). 
    1947  */ 
    1948     void opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") 
    1949     { 
    1950         static if (is(typeof(stuff[]))) 
    1951         { 
    1952             insertBack(stuff[]); 
    1953         } 
    1954         else 
    1955         { 
    1956             insertBack(stuff); 
    1957         } 
    1958     } 
    1959  
    1960 /** 
    1961 Removes all contents from the container. The container decides how $(D 
    1962 capacity) is affected. 
    1963  
    1964 Postcondition: $(D empty) 
    1965  
    1966 Complexity: $(BIGOH n) 
    1967  */ 
    1968     void clear() 
    1969     { 
    1970         _data = null; 
    1971     } 
    1972  
    1973 /** 
    1974 Sets the number of elements in the container to $(D newSize). If $(D 
    1975 newSize) is greater than $(D length), the added elements are added to 
    1976 unspecified positions in the container and initialized with $(D 
    1977 ElementType.init). 
    1978  
    1979 Complexity: $(BIGOH abs(n - newLength)) 
    1980  
    1981 Postcondition: $(D length == newLength) 
    1982  */ 
    1983     @property void length(size_t newLength) 
    1984     { 
    1985         size_t startEmplace = void; 
    1986         if (!_data) 
    1987         { 
    1988             _data = emplace!Data(malloc(Data.sizeof)[0 .. Data.sizeof], 
    1989                     (cast(T*) malloc(T.sizeof * newLength))[0 .. newLength]); 
    1990             startEmplace = 0; 
    1991         } 
    1992         else 
    1993         { 
    1994             if (length >= newLength) 
    1995             { 
    1996                 // shorten 
    1997                 _data._payload = _data._payload.ptr[0 .. newLength]; 
    1998                 return; 
    1999             } 
    2000             else 
    2001             { 
    2002                 // enlarge 
    2003                 startEmplace = length; 
    2004                 _data._payload = (cast(T*) realloc(_data._payload.ptr, 
    2005                                 T.sizeof * newLength))[0 .. newLength]; 
    2006             } 
    2007         } 
    2008         foreach (ref e; _data._payload[startEmplace .. $]) 
    2009         { 
    2010             static init = T.init; 
    2011             memcpy(&e, &init, T.sizeof); 
    2012         } 
    2013     } 
    2014  
    2015 /** 
    2016 Picks one value in an unspecified position in the container, removes 
    2017 it from the container, and returns it. Implementations should pick the 
    2018 value that's the most advantageous for the container, but document the 
    2019 exact behavior. The stable version behaves the same, but guarantees 
    2020 that ranges iterating over the container are never invalidated. 
    2021  
    2022 Precondition: $(D !empty) 
    2023  
    2024 Returns: The element removed. 
    2025  
    2026 Complexity: $(BIGOH log(n)). 
    2027  */ 
    2028     T removeAny() 
    2029     { 
    2030         auto result = back; 
    2031         removeBack(); 
    2032         return result; 
    2033     } 
    2034     /// ditto 
    2035     alias removeAny stableRemoveAny; 
    2036  
    2037 /** 
    2038 Inserts $(D value) to the front or back of the container. $(D stuff) 
    2039 can be a value convertible to $(D ElementType) or a range of objects 
    2040 convertible to $(D ElementType). The stable version behaves the same, 
    2041 but guarantees that ranges iterating over the container are never 
    2042 invalidated. 
    2043  
    2044 Returns: The number of elements inserted 
    2045  
    2046 Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
    2047 elements in $(D stuff) 
    2048  */ 
    2049     size_t insertBack(Stuff)(Stuff stuff) 
    2050     if (isImplicitlyConvertible!(Stuff, T)) 
    2051     { 
    2052         if (capacity == length) 
    2053         { 
    2054             reserve(1 + capacity * 3 / 2); 
    2055             assert(capacity > length); 
    2056         } 
    2057         assert(_data); 
    2058         emplace!T((cast(void*) (_data._payload.ptr + _data._payload.length)) 
    2059                 [0 .. T.sizeof], 
    2060                 stuff); 
    2061         _data._payload = _data._payload.ptr[0 .. _data._payload.length + 1]; 
    2062         return 1; 
    2063     } 
    2064  
    2065 /// ditto 
    2066     size_t insertBack(Stuff)(Stuff stuff) 
    2067     if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
    2068     { 
    2069         size_t result; 
    2070         foreach (item; stuff) 
    2071         { 
    2072             insertBack(item); 
    2073             ++result; 
    2074         } 
    2075         return result; 
    2076     } 
    2077 /// ditto 
    2078     alias insertBack insert; 
    2079  
    2080 /** 
    2081 Removes the value at the back of the container. The stable version 
    2082 behaves the same, but guarantees that ranges iterating over the 
    2083 container are never invalidated. 
    2084  
    2085 Precondition: $(D !empty) 
    2086  
    2087 Complexity: $(BIGOH log(n)). 
    2088  */ 
    2089     void removeBack() 
    2090     { 
    2091         enforce(!empty); 
    2092         _data._payload = _data._payload[0 .. $ - 1]; 
    2093     } 
    2094 /// ditto 
    2095     alias removeBack stableRemoveBack; 
    2096  
    2097 /** 
    2098 Removes $(D howMany) values at the front or back of the 
    2099 container. Unlike the unparameterized versions above, these functions 
    2100 do not throw if they could not remove $(D howMany) elements. Instead, 
    2101 if $(D howMany > n), all elements are removed. The returned value is 
    2102 the effective number of elements removed. The stable version behaves 
    2103 the same, but guarantees that ranges iterating over the container are 
    2104 never invalidated. 
    2105  
    2106 Returns: The number of elements removed 
    2107  
    2108 Complexity: $(BIGOH howMany). 
    2109  */ 
    2110     size_t removeBack(size_t howMany) 
    2111     { 
    2112         if (howMany > length) howMany = length; 
    2113         _data._payload = _data._payload[0 .. $ - howMany]; 
    2114         return howMany; 
    2115     } 
    2116     /// ditto 
    2117     alias removeBack stableRemoveBack; 
    2118  
    2119 /** 
    2120 Inserts $(D stuff) before, after, or instead range $(D r), which must 
    2121 be a valid range previously extracted from this container. $(D stuff) 
    2122 can be a value convertible to $(D ElementType) or a range of objects 
    2123 convertible to $(D ElementType). The stable version behaves the same, 
    2124 but guarantees that ranges iterating over the container are never 
    2125 invalidated. 
    2126  
    2127 Returns: The number of values inserted. 
    2128  
    2129 Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) 
    2130  */ 
     1836     */ 
    21311837    size_t insertBefore(Stuff)(Range r, Stuff stuff) 
    21321838    if (isImplicitlyConvertible!(Stuff, T)) 
    21331839    { 
    2134         enforce(r._data == _data && r._a < length); 
     1840        enforce(r._outer._data == _data && r._a < length); 
    21351841        reserve(length + 1); 
    2136         assert(_data); 
     1842        assert(_data.RefCounted.isInitialized); 
    21371843        // Move elements over by one slot 
    21381844        memmove(_data._payload.ptr + r._a + 1, 
    21391845                _data._payload.ptr + r._a, 
    21401846                T.sizeof * (length - r._a)); 
    21411847        emplace!T((cast(void*) (_data._payload.ptr + r._a))[0 .. T.sizeof], 
    21421848                stuff); 
    21431849        _data._payload = _data._payload.ptr[0 .. _data._payload.length + 1]; 
    21441850        return 1; 
    21451851    } 
    21461852 
    21471853/// ditto 
    21481854    size_t insertBefore(Stuff)(Range r, Stuff stuff) 
    21491855    if (isInputRange!Stuff && isImplicitlyConvertible!(ElementType!Stuff, T)) 
    21501856    { 
    2151         enforce(r._data == _data && r._a < length); 
     1857        enforce(r._outer._data == _data && r._a <= length); 
    21521858        static if (isForwardRange!Stuff) 
    21531859        { 
    21541860            // Can find the length in advance 
    21551861            auto extra = walkLength(stuff); 
    21561862            if (!extra) return 0; 
    21571863            reserve(length + extra); 
    2158             assert(_data); 
     1864            assert(_data.RefCounted.isInitialized); 
    21591865            // Move elements over by extra slots 
    21601866            memmove(_data._payload.ptr + r._a + extra, 
    21611867                    _data._payload.ptr + r._a, 
    21621868                    T.sizeof * (length - r._a)); 
    21631869            foreach (p; _data._payload.ptr + r._a .. 
    21641870                    _data._payload.ptr + r._a + extra) 
    21651871            { 
    21661872                emplace!T((cast(void*) p)[0 .. T.sizeof], stuff.front); 
    21671873                stuff.popFront(); 
    21681874            } 
     
    22431949never invalidated. 
    22441950 
    22451951Returns: A range spanning the remaining elements in the container that 
    22461952initially were right after $(D r). 
    22471953 
    22481954Complexity: $(BIGOH n - m), where $(D m) is the number of elements in 
    22491955$(D r) 
    22501956 */ 
    22511957    Range linearRemove(Range r) 
    22521958    { 
    2253         enforce(_data); 
     1959        enforce(_data.RefCounted.isInitialized); 
    22541960        enforce(r._a <= r._b && r._b <= length); 
    22551961        immutable offset1 = r._a; 
    22561962        immutable offset2 = r._b; 
    22571963        immutable tailLength = length - offset2; 
    22581964        // Use copy here, not a[] = b[] because the ranges may overlap 
    22591965        copy(this[offset2 .. length], this[offset1 .. offset1 + tailLength]); 
    22601966        length = offset1 + tailLength; 
    22611967        return this[length - tailLength .. length]; 
    22621968    } 
    22631969 
    22641970    /// ditto 
    22651971    alias remove stableLinearRemove; 
    22661972 
    22671973} 
    22681974 
     1975// unittest 
     1976// { 
     1977//     Array!int a; 
     1978//     assert(a.empty); 
     1979// } 
     1980 
    22691981unittest 
    22701982{ 
    2271     Array!int a; 
    2272     assert(a.empty); 
    2273 
    2274  
    2275 unittest 
    2276 
    2277     auto a = Array!int(1, 2, 3); 
     1983    Array!int a = Array!int(1, 2, 3); 
     1984    //a._data._refCountedDebug = true; 
    22781985    auto b = a.dup; 
    22791986    assert(b == Array!int(1, 2, 3)); 
    22801987    b.front = 42; 
    22811988    assert(b == Array!int(42, 2, 3)); 
    22821989    assert(a == Array!int(1, 2, 3)); 
    22831990} 
    22841991 
    22851992unittest 
    22861993{ 
    22871994    auto a = Array!int(1, 2, 3); 
     
    23072014{ 
    23082015    auto a = Array!int(1, 2, 3); 
    23092016    a[1] *= 42; 
    23102017    assert(a[1] == 84); 
    23112018} 
    23122019 
    23132020unittest 
    23142021{ 
    23152022    auto a = Array!int(1, 2, 3); 
    23162023    auto b = Array!int(11, 12, 13); 
    2317     assert(a ~ b == Array!int(1, 2, 3, 11, 12, 13)); 
    2318     assert(a ~ b[] == Array!int(1, 2, 3, 11, 12, 13)); 
     2024    auto c = a ~ b; 
     2025    //foreach (e; c) writeln(e); 
     2026    assert(c == Array!int(1, 2, 3, 11, 12, 13)); 
     2027    //assert(a ~ b[] == Array!int(1, 2, 3, 11, 12, 13)); 
    23192028} 
    23202029 
    23212030unittest 
    23222031{ 
    23232032    auto a = Array!int(1, 2, 3); 
    23242033    auto b = Array!int(11, 12, 13); 
    23252034    a ~= b; 
    23262035    assert(a == Array!int(1, 2, 3, 11, 12, 13)); 
    23272036} 
    23282037 
     
    23422051    r = a[2 .. 2]; 
    23432052    assert(a.insertBefore(r, [8, 9]) == 2); 
    23442053    assert(a == Array!int(1, 2, 8, 9, 42, 3, 4, 5)); 
    23452054} 
    23462055 
    23472056unittest 
    23482057{ 
    23492058    auto a = Array!int(0, 1, 2, 3, 4, 5, 6, 7, 8); 
    23502059    a.linearRemove(a[4 .. 6]); 
    23512060    auto b = Array!int(0, 1, 2, 3, 6, 7, 8); 
     2061    //writeln(a.length); 
     2062    //foreach (e; a) writeln(e); 
    23522063    assert(a == Array!int(0, 1, 2, 3, 6, 7, 8)); 
    23532064} 
    23542065 
    23552066// BinaryHeap 
    23562067/** 
    23572068Implements a $(WEB en.wikipedia.org/wiki/Binary_heap, binary heap) 
    23582069container on top of a given random-access range type (usually $(D 
    23592070T[])) or a random-access container type (usually $(D Array!T)). The 
    23602071documentation of $(D BinaryHeap) will refer to the underlying range or 
    23612072container as the $(I store) of the heap. 
     
    24002111//private: 
    24012112 
    24022113    // The payload includes the support store and the effective length 
    24032114    private RefCounted!(Tuple!(Store, "_store", size_t, "_length"), 
    24042115                       RefCountedAutoInitialize.no) _payload; 
    24052116    // Comparison predicate 
    24062117    private alias binaryFun!(less) comp; 
    24072118    // Convenience accessors 
    24082119    private @property ref Store _store() 
    24092120    { 
    2410         assert(_payload.refCountedIsInitialized); 
     2121        assert(_payload.RefCounted.isInitialized); 
    24112122        return _payload._store; 
    24122123    } 
    24132124    private @property ref size_t _length() 
    24142125    { 
    2415         assert(_payload.refCountedIsInitialized); 
     2126        assert(_payload.RefCounted.isInitialized); 
    24162127        return _payload._length; 
    24172128    } 
    24182129 
    24192130    // Asserts that the heap property is respected. 
    24202131    private void assertValid() 
    24212132    { 
    24222133        debug 
    24232134        { 
    2424             if (!_payload.refCountedIsInitialized) return; 
     2135            if (!_payload.RefCounted.isInitialized) return; 
    24252136            if (_length < 2) return; 
    24262137            for (size_t n = _length - 1; n >= 1; --n) 
    24272138            { 
    24282139                auto parentIdx = (n - 1) / 2; 
    24292140                assert(!comp(_store[parentIdx], _store[n]), text(n)); 
    24302141            } 
    24312142        } 
    24322143    } 
    24332144 
    24342145    // Assuming the element at index i perturbs the heap property in 
     
    24842195        { 
    24852196            auto t1 = _store[].moveAt(i); 
    24862197            auto t2 = _store[].moveAt(j); 
    24872198            _store[i] = move(t2); 
    24882199            _store[j] = move(t1); 
    24892200        } 
    24902201    } 
    24912202 
    24922203public: 
    24932204 
    2494 /** 
    2495 Converts the store $(D s) into a heap. If $(D initialSize) is 
    2496 specified, only the first $(D initialSize) elements in $(D s) are 
    2497 transformed into a heap, after which the heap can grow up to $(D 
    2498 r.length) (if $(D Store) is a range) or indefinitely (if $(D Store) is 
    2499 a container with $(D insertBack)). Performs $(BIGOH min(r.length, 
    2500 initialSize)) evaluations of $(D less). 
    2501  */ 
     2205    /** 
     2206       Converts the store $(D s) into a heap. If $(D initialSize) is 
     2207       specified, only the first $(D initialSize) elements in $(D s) 
     2208       are transformed into a heap, after which the heap can grow up 
     2209       to $(D r.length) (if $(D Store) is a range) or indefinitely (if 
     2210       $(D Store) is a container with $(D insertBack)). Performs 
     2211       $(BIGOH min(r.length, initialSize)) evaluations of $(D less). 
     2212     */ 
    25022213    this(Store s, size_t initialSize = size_t.max) 
    25032214    { 
    25042215        acquire(s, initialSize); 
    25052216    } 
    25062217 
    25072218/** 
    25082219Takes ownership of a store. After this, manipulating $(D s) may make 
    25092220the heap work incorrectly. 
    25102221 */ 
    25112222    void acquire(Store s, size_t initialSize = size_t.max) 
    25122223    { 
    2513         _payload.refCountedEnsureInitialized(); 
     2224        _payload.RefCounted.ensureInitialized(); 
    25142225        _store() = move(s); 
    25152226        _length() = min(_store.length, initialSize); 
    25162227        if (_length < 2) return; 
    25172228        for (auto i = (_length - 2) / 2; ; ) 
    25182229        { 
    25192230            this.percolateDown(_store, i, _length); 
    25202231            if (i-- == 0) break; 
    25212232        } 
    25222233        assertValid; 
    25232234    } 
    25242235 
    25252236/** 
    25262237Takes ownership of a store assuming it already was organized as a 
    25272238heap. 
    25282239 */ 
    25292240    void assume(Store s, size_t initialSize = size_t.max) 
    25302241    { 
    2531         _payload.refCountedEnsureInitialized(); 
     2242        _payload.RefCounted.ensureInitialized(); 
    25322243        _store() = s; 
    25332244        _length() = min(_store.length, initialSize); 
    25342245        assertValid; 
    25352246    } 
    25362247 
    25372248/** 
    25382249Clears the heap. Returns the portion of the store from $(D 0) up to 
    25392250$(D length), which satisfies the $(LUCKY heap property). 
    25402251 */ 
    25412252    auto release() 
    25422253    { 
    2543         if (!_payload.refCountedIsInitialized) 
     2254        if (!_payload.RefCounted.isInitialized) 
    25442255        { 
    25452256            return typeof(_store[0 .. _length]).init; 
    25462257        } 
    25472258        assertValid(); 
    25482259        auto result = _store[0 .. _length]; 
    25492260        _payload = _payload.init; 
    25502261        return result; 
    25512262    } 
    25522263 
    25532264/** 
     
    25582269        return !length; 
    25592270    } 
    25602271 
    25612272/** 
    25622273Returns a duplicate of the heap. The underlying store must also 
    25632274support a $(D dup) method. 
    25642275 */ 
    25652276    @property BinaryHeap dup() 
    25662277    { 
    25672278        BinaryHeap result; 
    2568         if (!_payload.refCountedIsInitialized) return result; 
     2279        if (!_payload.RefCounted.isInitialized) return result; 
    25692280        result.assume(_store.dup, length); 
    25702281        return result; 
    25712282    } 
    25722283 
    25732284/** 
    25742285Returns the _length of the heap. 
    25752286 */ 
    25762287    @property size_t length() 
    25772288    { 
    2578         return _payload.refCountedIsInitialized ? _length : 0; 
     2289        return _payload.RefCounted.isInitialized ? _length : 0; 
    25792290    } 
    25802291 
    25812292/** 
    25822293Returns the _capacity of the heap, which is the length of the 
    25832294underlying store (if the store is a range) or the _capacity of the 
    25842295underlying store (if the store is a container). 
    25852296 */ 
    25862297    @property size_t capacity() 
    25872298    { 
    2588         if (!_payload.refCountedIsInitialized) return 0; 
     2299        if (!_payload.RefCounted.isInitialized) return 0; 
    25892300        static if (is(typeof(_store.capacity) : size_t)) 
    25902301        { 
    25912302            return _store.capacity; 
    25922303        } 
    25932304        else 
    25942305        { 
    25952306            return _store.length; 
    25962307        } 
    25972308    } 
    25982309 
     
    26152326    } 
    26162327 
    26172328/** 
    26182329Inserts $(D value) into the store. If the underlying store is a range 
    26192330and $(D length == capacity), throws an exception. 
    26202331 */ 
    26212332    size_t insert(ElementType!Store value) 
    26222333    { 
    26232334        static if (is(_store.insertBack(value))) 
    26242335        { 
    2625             _payload.refCountedEnsureInitialized(); 
     2336            _payload.RefCounted.ensureInitialized(); 
    26262337            if (length == _store.length) 
    26272338            { 
    26282339                // reallocate 
    26292340                _store.insertBack(value); 
    26302341            } 
    26312342            else 
    26322343            { 
    26332344                // no reallocation 
    26342345                _store[_length] = value; 
    26352346            } 
     
    27002411/** 
    27012412If the heap has room to grow, inserts $(D value) into the store and 
    27022413returns $(D true). Otherwise, if $(D less(value, front)), calls $(D 
    27032414replaceFront(value)) and returns again $(D true). Otherwise, leaves 
    27042415the heap unaffected and returns $(D false). This method is useful in 
    27052416scenarios where the smallest $(D k) elements of a set of candidates 
    27062417must be collected. 
    27072418 */ 
    27082419    bool conditionalInsert(ElementType!Store value) 
    27092420    { 
    2710         _payload.refCountedEnsureInitialized(); 
     2421        _payload.RefCounted.ensureInitialized(); 
    27112422        if (_length < _store.length) 
    27122423        { 
    27132424            insert(value); 
    27142425            return true; 
    27152426        } 
    27162427        // must replace the top 
    27172428        assert(!_store.empty); 
    27182429        if (!comp(value, _store.front)) return false; // value >= largest 
    27192430        _store.front = value; 
    27202431        percolateDown(_store, 0, _length); 
     
    27532464        int[] b = new int[a.length]; 
    27542465        BinaryHeap!(int[]) h = BinaryHeap!(int[])(b, 0); 
    27552466        foreach (e; a) 
    27562467        { 
    27572468            h.insert(e); 
    27582469        } 
    27592470        assert(b == [ 16, 14, 10, 8, 7, 3, 9, 1, 4, 2 ], text(b)); 
    27602471    } 
    27612472} 
    27622473 
     2474//////////////////////////////////////////////////////////////////////////////// 
     2475// Array!bool 
     2476//////////////////////////////////////////////////////////////////////////////// 
     2477 
     2478/** 
     2479_Array specialized for $(D bool). Packs together values efficiently by 
     2480allocating one bit per element. 
     2481 */ 
     2482struct Array(T) if (is(T == bool)) 
     2483{ 
     2484    static immutable uint bitsPerWord = size_t.sizeof * 8; 
     2485    private alias Tuple!(Array!(size_t).Payload, "_backend", ulong, "_length") 
     2486    Data; 
     2487    private RefCounted!(Data, RefCountedAutoInitialize.no) _store; 
     2488 
     2489    private ref size_t[] data() 
     2490    { 
     2491        assert(_store.RefCounted.isInitialized); 
     2492        return _store._backend._payload; 
     2493    } 
     2494 
     2495    private ref size_t dataCapacity() 
     2496    { 
     2497        return _store._backend._capacity; 
     2498    } 
     2499 
     2500    /** 
     2501       Defines the container's primary range. 
     2502     */ 
     2503    struct Range 
     2504    { 
     2505        private Array!bool _outer; 
     2506        private ulong _a, _b; 
     2507        /// Range primitives 
     2508        @property Range save() 
     2509        { 
     2510            version (bug4437) 
     2511            { 
     2512                return this; 
     2513            } 
     2514            else 
     2515            { 
     2516                auto copy = this; 
     2517                return copy; 
     2518            } 
     2519        } 
     2520        /// Ditto 
     2521        @property bool empty() 
     2522        { 
     2523            return _a >= _b || _outer.length < _b; 
     2524        } 
     2525        /// Ditto 
     2526        @property T front() 
     2527        { 
     2528            enforce(!empty); 
     2529            return _outer[_a]; 
     2530        } 
     2531        /// Ditto 
     2532        @property void front(bool value) 
     2533        { 
     2534            enforce(!empty); 
     2535            _outer[_a] = value; 
     2536        } 
     2537        /// Ditto 
     2538        T moveFront() 
     2539        { 
     2540            enforce(!empty); 
     2541            return _outer.moveAt(_a); 
     2542        } 
     2543        /// Ditto 
     2544        void popFront() 
     2545        { 
     2546            enforce(!empty); 
     2547            ++_a; 
     2548        } 
     2549        /// Ditto 
     2550        @property T back() 
     2551        { 
     2552            enforce(!empty); 
     2553            return _outer[_b - 1]; 
     2554        } 
     2555        /// Ditto 
     2556        T moveBack() 
     2557        { 
     2558            enforce(!empty); 
     2559            return _outer.moveAt(_b - 1); 
     2560        } 
     2561        /// Ditto 
     2562        void popBack() 
     2563        { 
     2564            enforce(!empty); 
     2565            --_b; 
     2566        } 
     2567        /// Ditto 
     2568        T opIndex(size_t i) 
     2569        { 
     2570            return _outer[_a + i]; 
     2571        } 
     2572        /// Ditto 
     2573        void opIndexAssign(T value, uint i) 
     2574        { 
     2575            _outer[_a + i] = value; 
     2576        } 
     2577        /// Ditto 
     2578        T moveAt(size_t i) 
     2579        { 
     2580            return _outer.moveAt(_a + i); 
     2581        } 
     2582        /// Ditto 
     2583        @property ulong length() const 
     2584        { 
     2585            assert(_a <= _b); 
     2586            return _b - _a; 
     2587        } 
     2588    } 
     2589 
     2590    /** 
     2591       Property returning $(D true) if and only if the container has 
     2592       no elements. 
     2593 
     2594       Complexity: $(BIGOH 1) 
     2595     */ 
     2596    @property bool empty() 
     2597    { 
     2598        return !length; 
     2599    } 
     2600 
     2601    unittest 
     2602    { 
     2603        Array!bool a; 
     2604        //a._store._refCountedDebug = true; 
     2605        assert(a.empty); 
     2606        a.insertBack(false); 
     2607        assert(!a.empty); 
     2608    } 
     2609 
     2610    /** 
     2611       Returns a duplicate of the container. The elements themselves 
     2612       are not transitively duplicated. 
     2613 
     2614       Complexity: $(BIGOH n). 
     2615     */ 
     2616    @property Array!bool dup() 
     2617    { 
     2618        Array!bool result; 
     2619        result.insertBack(this[]); 
     2620        return result; 
     2621    } 
     2622 
     2623    unittest 
     2624    { 
     2625        Array!bool a; 
     2626        assert(a.empty); 
     2627        auto b = a.dup; 
     2628        assert(b.empty); 
     2629        a.insertBack(true); 
     2630        assert(b.empty); 
     2631    } 
     2632 
     2633    /** 
     2634       Returns the number of elements in the container. 
     2635 
     2636       Complexity: $(BIGOH log(n)). 
     2637    */ 
     2638    @property ulong length() 
     2639    { 
     2640        return _store.RefCounted.isInitialized ? _store._length : 0; 
     2641    } 
     2642 
     2643    unittest 
     2644    { 
     2645        Array!bool a; 
     2646        assert(a.length == 0); 
     2647        a.insert(true); 
     2648        assert(a.length == 1, text(a.length)); 
     2649    } 
     2650 
     2651    /** 
     2652       Returns the maximum number of elements the container can store 
     2653       without (a) allocating memory, (b) invalidating iterators upon 
     2654       insertion. 
     2655 
     2656       Complexity: $(BIGOH log(n)). 
     2657     */ 
     2658    @property ulong capacity() 
     2659    { 
     2660        return _store.RefCounted.isInitialized 
     2661            ? cast(ulong) bitsPerWord * _store._backend.capacity 
     2662            : 0; 
     2663    } 
     2664 
     2665    unittest 
     2666    { 
     2667        Array!bool a; 
     2668        assert(a.capacity == 0); 
     2669        foreach (i; 0 .. 100) 
     2670        { 
     2671            a.insert(true); 
     2672            assert(a.capacity >= a.length, text(a.capacity)); 
     2673        } 
     2674    } 
     2675 
     2676    /** 
     2677       Ensures sufficient capacity to accommodate $(D n) elements. 
     2678 
     2679       Postcondition: $(D capacity >= n) 
     2680 
     2681       Complexity: $(BIGOH log(e - capacity)) if $(D e > capacity), 
     2682       otherwise $(BIGOH 1). 
     2683     */ 
     2684    void reserve(ulong e) 
     2685    { 
     2686        _store.RefCounted.ensureInitialized(); 
     2687        _store._backend.reserve(to!size_t((e + bitsPerWord - 1) / bitsPerWord)); 
     2688    } 
     2689 
     2690    unittest 
     2691    { 
     2692        Array!bool a; 
     2693        assert(a.capacity == 0); 
     2694        a.reserve(15657); 
     2695        assert(a.capacity >= 15657); 
     2696    } 
     2697 
     2698    /** 
     2699       Returns a range that iterates over all elements of the 
     2700       container, in a container-defined order. The container should 
     2701       choose the most convenient and fast method of iteration for $(D 
     2702       opSlice()). 
     2703 
     2704       Complexity: $(BIGOH log(n)) 
     2705     */ 
     2706    Range opSlice() 
     2707    { 
     2708        return Range(this, 0, length); 
     2709    } 
     2710 
     2711    unittest 
     2712    { 
     2713        Array!bool a; 
     2714        a.insertBack([true, false, true, true]); 
     2715        assert(a[].length == 4); 
     2716    } 
     2717 
     2718    /** 
     2719       Returns a range that iterates the container between two 
     2720       specified positions. 
     2721 
     2722       Complexity: $(BIGOH log(n)) 
     2723     */ 
     2724    Range opSlice(ulong a, ulong b) 
     2725    { 
     2726        enforce(a <= b && b <= length); 
     2727        return Range(this, a, b); 
     2728    } 
     2729 
     2730    unittest 
     2731    { 
     2732        Array!bool a; 
     2733        a.insertBack([true, false, true, true]); 
     2734        assert(a[0 .. 2].length == 2); 
     2735    } 
     2736 
     2737    /** 
     2738       Equivalent to $(D opSlice().front) and $(D opSlice().back), 
     2739       respectively. 
     2740 
     2741       Complexity: $(BIGOH log(n)) 
     2742     */ 
     2743    @property bool front() 
     2744    { 
     2745        enforce(!empty); 
     2746        return data.ptr[0] & 1; 
     2747    } 
     2748 
     2749    /// Ditto 
     2750    @property void front(bool value) 
     2751    { 
     2752        enforce(!empty); 
     2753        if (value) data.ptr[0] |= 1; 
     2754        else data.ptr[0] &= ~cast(size_t) 1; 
     2755    } 
     2756 
     2757    unittest 
     2758    { 
     2759        Array!bool a; 
     2760        a.insertBack([true, false, true, true]); 
     2761        assert(a.front); 
     2762        a.front = false; 
     2763        assert(!a.front); 
     2764    } 
     2765 
     2766    /// Ditto 
     2767    @property bool back() 
     2768    { 
     2769        enforce(!empty); 
     2770        return data.back & (1u << ((_store._length - 1) % bitsPerWord)); 
     2771    } 
     2772 
     2773    /// Ditto 
     2774    @property void back(bool value) 
     2775    { 
     2776        enforce(!empty); 
     2777        if (value) 
     2778        { 
     2779            data.back |= (1u << ((_store._length - 1) % bitsPerWord)); 
     2780        } 
     2781        else 
     2782        { 
     2783            data.back &= 
     2784                ~(cast(size_t)1 << ((_store._length - 1) % bitsPerWord)); 
     2785        } 
     2786    } 
     2787 
     2788    unittest 
     2789    { 
     2790        Array!bool a; 
     2791        a.insertBack([true, false, true, true]); 
     2792        assert(a.back); 
     2793        a.back = false; 
     2794        assert(!a.back); 
     2795    } 
     2796 
     2797    /** 
     2798       Indexing operators yield or modify the value at a specified index. 
     2799     */ 
     2800    bool opIndex(ulong i) 
     2801    { 
     2802        auto div = cast(size_t) (i / bitsPerWord); 
     2803        auto rem = i % bitsPerWord; 
     2804        enforce(div < data.length); 
     2805        return data.ptr[div] & (1u << rem); 
     2806    } 
     2807    /// ditto 
     2808    void opIndexAssign(bool value, ulong i) 
     2809    { 
     2810        auto div = cast(size_t) (i / bitsPerWord); 
     2811        auto rem = i % bitsPerWord; 
     2812        enforce(div < data.length); 
     2813        if (value) data.ptr[div] |= (1u << rem); 
     2814        else data.ptr[div] &= ~(cast(size_t)1 << rem); 
     2815    } 
     2816    /// ditto 
     2817    void opIndexOpAssign(string op)(bool value, ulong i) 
     2818    { 
     2819        auto div = cast(size_t) (i / bitsPerWord); 
     2820        auto rem = i % bitsPerWord; 
     2821        enforce(div < data.length); 
     2822        auto oldValue = cast(bool) (data.ptr[div] & (1u << rem)); 
     2823        // Do the deed 
     2824        auto newValue = mixin("oldValue "~op~" value"); 
     2825        // Write back the value 
     2826        if (newValue != oldValue) 
     2827        { 
     2828            if (newValue) data.ptr[div] |= (1u << rem); 
     2829            else data.ptr[div] &= ~(cast(size_t)1 << rem); 
     2830        } 
     2831    } 
     2832    /// Ditto 
     2833    T moveAt(ulong i) 
     2834    { 
     2835        return this[i]; 
     2836    } 
     2837 
     2838    unittest 
     2839    { 
     2840        Array!bool a; 
     2841        a.insertBack([true, false, true, true]); 
     2842        assert(a[0] && !a[1]); 
     2843        a[0] &= a[1]; 
     2844        assert(!a[0]); 
     2845    } 
     2846 
     2847    /** 
     2848       Returns a new container that's the concatenation of $(D this) 
     2849       and its argument. 
     2850 
     2851       Complexity: $(BIGOH n + m), where m is the number of elements 
     2852       in $(D stuff) 
     2853     */ 
     2854    Array!bool opBinary(string op, Stuff)(Stuff rhs) if (op == "~") 
     2855    { 
     2856        auto result = this; 
     2857        return result ~= rhs; 
     2858    } 
     2859 
     2860    unittest 
     2861    { 
     2862        Array!bool a; 
     2863        a.insertBack([true, false, true, true]); 
     2864        Array!bool b; 
     2865        b.insertBack([true, true, false, true]); 
     2866        assert(equal((a ~ b)[], 
     2867                        [true, false, true, true, true, true, false, true])); 
     2868    } 
     2869 
     2870    // /// ditto 
     2871    // TotalContainer opBinaryRight(Stuff, string op)(Stuff lhs) if (op == "~") 
     2872    // { 
     2873    //     assert(0); 
     2874    // } 
     2875 
     2876    /** 
     2877       Forwards to $(D insertAfter(this[], stuff)). 
     2878     */ 
     2879    // @@@BUG@@@ 
     2880    //ref Array!bool opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") 
     2881    Array!bool opOpAssign(string op, Stuff)(Stuff stuff) if (op == "~") 
     2882    { 
     2883        static if (is(typeof(stuff[]))) insertBack(stuff[]); 
     2884        else insertBack(stuff); 
     2885        return this; 
     2886    } 
     2887 
     2888    unittest 
     2889    { 
     2890        Array!bool a; 
     2891        a.insertBack([true, false, true, true]); 
     2892        Array!bool b; 
     2893        a.insertBack([false, true, false, true, true]); 
     2894        a ~= b; 
     2895        assert(equal( 
     2896                    a[], 
     2897                    [true, false, true, true, false, true, false, true, true])); 
     2898    } 
     2899 
     2900    /** 
     2901       Removes all contents from the container. The container decides 
     2902       how $(D capacity) is affected. 
     2903 
     2904       Postcondition: $(D empty) 
     2905 
     2906       Complexity: $(BIGOH n) 
     2907     */ 
     2908    void clear() 
     2909    { 
     2910        this = Array!bool(); 
     2911    } 
     2912 
     2913    unittest 
     2914    { 
     2915        Array!bool a; 
     2916        a.insertBack([true, false, true, true]); 
     2917        a.clear(); 
     2918        assert(a.capacity == 0); 
     2919    } 
     2920 
     2921    /** 
     2922       Sets the number of elements in the container to $(D 
     2923       newSize). If $(D newSize) is greater than $(D length), the 
     2924       added elements are added to the container and initialized with 
     2925       $(D ElementType.init). 
     2926 
     2927       Complexity: $(BIGOH abs(n - newLength)) 
     2928 
     2929       Postcondition: $(D _length == newLength) 
     2930     */ 
     2931    @property void length(ulong newLength) 
     2932    { 
     2933        _store.RefCounted.ensureInitialized(); 
     2934        auto newDataLength = 
     2935            to!size_t((newLength + bitsPerWord - 1) / bitsPerWord); 
     2936        _store._backend.length = newDataLength; 
     2937        _store._length = newLength; 
     2938    } 
     2939 
     2940    unittest 
     2941    { 
     2942        Array!bool a; 
     2943        a.length = 1057; 
     2944        assert(a.length == 1057); 
     2945        foreach (e; a) 
     2946        { 
     2947            assert(!e); 
     2948        } 
     2949    } 
     2950 
     2951    /** 
     2952       Inserts $(D stuff) in the container. $(D stuff) can be a value 
     2953       convertible to $(D ElementType) or a range of objects 
     2954       convertible to $(D ElementType). 
     2955 
     2956       The $(D stable) version guarantees that ranges iterating over 
     2957       the container are never invalidated. Client code that counts on 
     2958       non-invalidating insertion should use $(D stableInsert). 
     2959 
     2960       Returns: The number of elements added. 
     2961 
     2962       Complexity: $(BIGOH m * log(n)), where $(D m) is the number of 
     2963       elements in $(D stuff) 
     2964     */ 
     2965    alias insertBack insert; 
     2966    ///ditto 
     2967    alias insertBack stableInsert; 
     2968 
     2969    /** 
     2970       Same as $(D insert(stuff)) and $(D stableInsert(stuff)) 
     2971       respectively, but relax the complexity constraint to linear. 
     2972     */ 
     2973    alias insertBack linearInsert; 
     2974    ///ditto 
     2975    alias insertBack stableLinearInsert; 
     2976 
     2977    /** 
     2978       Picks one value in the container, removes it from the 
     2979       container, and returns it. The stable version behaves the same, 
     2980       but guarantees that ranges iterating over the container are 
     2981       never invalidated. 
     2982 
     2983       Precondition: $(D !empty) 
     2984 
     2985       Returns: The element removed. 
     2986 
     2987       Complexity: $(BIGOH log(n)) 
     2988     */ 
     2989    T removeAny() 
     2990    { 
     2991        auto result = back(); 
     2992        removeBack(); 
     2993        return result; 
     2994    } 
     2995    /// ditto 
     2996    alias removeAny stableRemoveAny; 
     2997 
     2998    unittest 
     2999    { 
     3000        Array!bool a; 
     3001        a.length = 1057; 
     3002        assert(!a.removeAny()); 
     3003        assert(a.length == 1056); 
     3004        foreach (e; a) 
     3005        { 
     3006            assert(!e); 
     3007        } 
     3008    } 
     3009 
     3010    /** 
     3011       Inserts $(D value) to the back of the container. $(D stuff) can 
     3012       be a value convertible to $(D ElementType) or a range of 
     3013       objects convertible to $(D ElementType). The stable version 
     3014       behaves the same, but guarantees that ranges iterating over the 
     3015       container are never invalidated. 
     3016 
     3017       Returns: The number of elements inserted 
     3018 
     3019       Complexity: $(BIGOH log(n)) 
     3020     */ 
     3021    ulong insertBack(Stuff)(Stuff stuff) if (is(Stuff : bool)) 
     3022    { 
     3023        _store.RefCounted.ensureInitialized(); 
     3024        auto rem = _store._length % bitsPerWord; 
     3025        if (rem) 
     3026        { 
     3027            // Fits within the current array 
     3028            if (stuff) 
     3029            { 
     3030                data[$ - 1] |= (1u << rem); 
     3031            } 
     3032            else 
     3033            { 
     3034                data[$ - 1] &= ~(1u << rem); 
     3035            } 
     3036        } 
     3037        else 
     3038        { 
     3039            // Need to add more data 
     3040            _store._backend.insertBack(stuff); 
     3041        } 
     3042        ++_store._length; 
     3043        return 1; 
     3044    } 
     3045    /// Ditto 
     3046    ulong insertBack(Stuff)(Stuff stuff) 
     3047    if (isInputRange!Stuff && is(ElementType!Stuff : bool)) 
     3048    { 
     3049        static if (!hasLength!Stuff) ulong result; 
     3050        for (; !stuff.empty; stuff.popFront()) 
     3051        { 
     3052            insertBack(stuff.front); 
     3053            static if (!hasLength!Stuff) ++result; 
     3054        } 
     3055        static if (!hasLength!Stuff) return result; 
     3056        else return stuff.length; 
     3057    } 
     3058    /// ditto 
     3059    alias insertBack stableInsertBack; 
     3060 
     3061    /** 
     3062       Removes the value at the front or back of the container. The 
     3063       stable version behaves the same, but guarantees that ranges 
     3064       iterating over the container are never invalidated. The 
     3065       optional parameter $(D howMany) instructs removal of that many 
     3066       elements. If $(D howMany > n), all elements are removed and no 
     3067       exception is thrown. 
     3068 
     3069       Precondition: $(D !empty) 
     3070 
     3071       Complexity: $(BIGOH log(n)). 
     3072     */ 
     3073    void removeBack() 
     3074    { 
     3075        enforce(_store._length); 
     3076        if (_store._length % bitsPerWord) 
     3077        { 
     3078            // Cool, just decrease the length 
     3079            --_store._length; 
     3080        } 
     3081        else 
     3082        { 
     3083            // Reduce the allocated space 
     3084            --_store._length; 
     3085            _store._backend.length = _store._backend.length - 1; 
     3086        } 
     3087    } 
     3088    /// ditto 
     3089    alias removeBack stableRemoveBack; 
     3090 
     3091    /** 
     3092       Removes $(D howMany) values at the front or back of the 
     3093       container. Unlike the unparameterized versions above, these 
     3094       functions do not throw if they could not remove $(D howMany) 
     3095       elements. Instead, if $(D howMany > n), all elements are 
     3096       removed. The returned value is the effective number of elements 
     3097       removed. The stable version behaves the same, but guarantees 
     3098       that ranges iterating over the container are never invalidated. 
     3099 
     3100       Returns: The number of elements removed 
     3101 
     3102       Complexity: $(BIGOH howMany * log(n)). 
     3103     */ 
     3104    /// ditto 
     3105    ulong removeBack(ulong howMany) 
     3106    { 
     3107        if (howMany >= length) 
     3108        { 
     3109            howMany = length; 
     3110            clear(); 
     3111        } 
     3112        else 
     3113        { 
     3114            length = length - howMany; 
     3115        } 
     3116        return howMany; 
     3117    } 
     3118 
     3119    unittest 
     3120    { 
     3121        Array!bool a; 
     3122        a.length = 1057; 
     3123        assert(a.removeBack(1000) == 1000); 
     3124        assert(a.length == 57); 
     3125        foreach (e; a) 
     3126        { 
     3127            assert(!e); 
     3128        } 
     3129    } 
     3130 
     3131    /** 
     3132       Inserts $(D stuff) before, after, or instead range $(D r), 
     3133       which must be a valid range previously extracted from this 
     3134       container. $(D stuff) can be a value convertible to $(D 
     3135       ElementType) or a range of objects convertible to $(D 
     3136       ElementType). The stable version behaves the same, but 
     3137       guarantees that ranges iterating over the container are never 
     3138       invalidated. 
     3139 
     3140       Returns: The number of values inserted. 
     3141 
     3142       Complexity: $(BIGOH n + m), where $(D m) is the length of $(D stuff) 
     3143     */ 
     3144    ulong insertBefore(Stuff)(Range r, Stuff stuff) 
     3145    { 
     3146        // TODO: make this faster, it moves one bit at a time 
     3147        immutable inserted = stableInsertBack(stuff); 
     3148        immutable tailLength = length - inserted; 
     3149        bringToFront( 
     3150            this[r._a .. tailLength], 
     3151            this[tailLength .. length]); 
     3152        return inserted; 
     3153    } 
     3154    /// ditto 
     3155    alias insertBefore stableInsertBefore; 
     3156 
     3157    unittest 
     3158    { 
     3159        Array!bool a; 
     3160        version (bugxxxx) 
     3161        { 
     3162            a._store.refCountedDebug = true; 
     3163        } 
     3164        a.insertBefore(a[], true); 
     3165        assert(a.length == 1, text(a.length)); 
     3166        a.insertBefore(a[], false); 
     3167        assert(a.length == 2, text(a.length)); 
     3168    } 
     3169 
     3170    /// ditto 
     3171    ulong insertAfter(Stuff)(Range r, Stuff stuff) 
     3172    { 
     3173        // TODO: make this faster, it moves one bit at a time 
     3174        immutable inserted = stableInsertBack(stuff); 
     3175        immutable tailLength = length - inserted; 
     3176        bringToFront( 
     3177            this[r._b .. tailLength], 
     3178            this[tailLength .. length]); 
     3179        return inserted; 
     3180    } 
     3181    /// ditto 
     3182    alias insertAfter stableInsertAfter; 
     3183 
     3184    unittest 
     3185    { 
     3186        Array!bool a; 
     3187        a.length = 10; 
     3188        a.insertAfter(a[0 .. 5], true); 
     3189        assert(a.length == 11, text(a.length)); 
     3190        assert(a[5]); 
     3191    } 
     3192    /// ditto 
     3193    size_t replace(Stuff)(Range r, Stuff stuff) if (is(Stuff : bool)) 
     3194    { 
     3195        if (!r.empty) 
     3196        { 
     3197            // There is room 
     3198            r.front = stuff; 
     3199            r.popFront(); 
     3200            linearRemove(r); 
     3201        } 
     3202        else 
     3203        { 
     3204            // No room, must insert 
     3205            insertBefore(r, stuff); 
     3206        } 
     3207        return 1; 
     3208    } 
     3209    /// ditto 
     3210    alias replace stableReplace; 
     3211 
     3212    unittest 
     3213    { 
     3214        Array!bool a; 
     3215        a.length = 10; 
     3216        a.replace(a[3 .. 5], true); 
     3217        assert(a.length == 9, text(a.length)); 
     3218        assert(a[3]); 
     3219    } 
     3220 
     3221    /** 
     3222       Removes all elements belonging to $(D r), which must be a range 
     3223       obtained originally from this container. The stable version 
     3224       behaves the same, but guarantees that ranges iterating over the 
     3225       container are never invalidated. 
     3226 
     3227       Returns: A range spanning the remaining elements in the container that 
     3228       initially were right after $(D r). 
     3229 
     3230       Complexity: $(BIGOH n) 
     3231     */ 
     3232    Range linearRemove(Range r) 
     3233    { 
     3234        copy(this[r._b .. length], this[r._a .. length]); 
     3235        length = length - r.length; 
     3236        return this[r._a .. length]; 
     3237    } 
     3238    /// ditto 
     3239    alias linearRemove stableLinearRemove; 
     3240} 
     3241 
     3242unittest 
     3243{ 
     3244    Array!bool a; 
     3245    assert(a.empty); 
     3246}