// Written in the D programming language. /** This module defines generic containers. Construction: To implement the different containers both struct and class based approaches have been used. $(REF make, std,container,util) allows for uniform construction with either approach. --- import std.container; // Construct a red-black tree and an array both containing the values 1, 2, 3. // RedBlackTree should typically be allocated using `new` RedBlackTree!int rbTree = new RedBlackTree!int(1, 2, 3); // But `new` should not be used with Array Array!int array = Array!int(1, 2, 3); // `make` hides the differences RedBlackTree!int rbTree2 = make!(RedBlackTree!int)(1, 2, 3); Array!int array2 = make!(Array!int)(1, 2, 3); --- Note that `make` can infer the element type from the given arguments. --- import std.container; auto rbTree = make!RedBlackTree(1, 2, 3); // RedBlackTree!int auto array = make!Array("1", "2", "3"); // Array!string --- Reference_semantics: All containers have reference semantics, which means that after assignment both variables refer to the same underlying data. To make a copy of a container, use the `c.dup` container primitive. --- import std.container, std.range; Array!int originalArray = make!(Array!int)(1, 2, 3); Array!int secondArray = originalArray; assert(equal(originalArray[], secondArray[])); // changing one instance changes the other one as well! originalArray[0] = 12; assert(secondArray[0] == 12); // secondArray now refers to an independent copy of originalArray secondArray = originalArray.dup; secondArray[0] = 1; // assert that originalArray has not been affected assert(originalArray[0] == 12); --- $(B Attention:) If the container is implemented as a class, using an uninitialized instance can cause a null pointer dereference. --- import std.container; RedBlackTree!int rbTree; rbTree.insert(5); // null pointer dereference --- Using an uninitialized struct-based container will work, because the struct intializes itself upon use; however, up to this point the container will not have an identity and assignment does not create two references to the same data. --- import std.container; // create an uninitialized array Array!int array1; // array2 does _not_ refer to array1 Array!int array2 = array1; array2.insertBack(42); // thus array1 will not be affected assert(array1.empty); // after initialization reference semantics work as expected array1 = array2; // now affects array2 as well array1.removeBack(); assert(array2.empty); --- It is therefore recommended to always construct containers using $(REF make, std,container,util). This is in fact necessary to put containers into another container. For example, to construct an `Array` of ten empty `Array`s, use the following that calls `make` ten times. --- import std.container, std.range; auto arrOfArrs = make!Array(generate!(() => make!(Array!int)).take(10)); --- Submodules: This module consists of the following submodules: $(UL $(LI The $(MREF std, container, array) module provides an array type with deterministic control of memory, not reliant on the GC unlike built-in arrays. ) $(LI The $(MREF std, container, binaryheap) module provides a binary heap implementation that can be applied to any user-provided random-access range. ) $(LI The $(MREF std, container, dlist) module provides a doubly-linked list implementation. ) $(LI The $(MREF std, container, rbtree) module implements red-black trees. ) $(LI The $(MREF std, container, slist) module implements singly-linked lists. ) $(LI The $(MREF std, container, util) module contains some generic tools commonly used by container implementations. ) ) The_primary_range_of_a_container: While some containers offer direct access to their elements e.g. via `opIndex`, `c.front` or `c.back`, access and modification of a container's contents is generally done through its primary $(MREF_ALTTEXT range, std, range) type, which is aliased as `C.Range`. For example, the primary range type of `Array!int` is `Array!int.Range`. If the documentation of a member function of a container takes a parameter of type `Range`, then it refers to the primary range type of this container. Oftentimes `Take!Range` will be used, in which case the range refers to a span of the elements in the container. Arguments to these parameters $(B must) be obtained from the same container instance as the one being worked with. It is important to note that many generic range algorithms return the same range type as their input range. --- import std.algorithm.comparison : equal; import std.algorithm.iteration : find; import std.container; import std.range : take; auto array = make!Array(1, 2, 3); // `find` returns an Array!int.Range advanced to the element "2" array.linearRemove(array[].find(2)); assert(array[].equal([1])); array = make!Array(1, 2, 3); // the range given to `linearRemove` is a Take!(Array!int.Range) // spanning just the element "2" array.linearRemove(array[].find(2).take(1)); assert(array[].equal([1, 3])); --- When any $(MREF_ALTTEXT range, std, range) can be passed as an argument to a member function, the documention usually refers to the parameter's templated type as `Stuff`. --- import std.algorithm.comparison : equal; import std.container; import std.range : iota; auto array = make!Array(1, 2); // the range type returned by `iota` is completely unrelated to Array, // which is fine for Array.insertBack: array.insertBack(iota(3, 10)); assert(array[].equal([1, 2, 3, 4, 5, 6, 7, 8, 9])); --- Container_primitives: Containers do not form a class hierarchy, instead they implement a common set of primitives (see table below). These primitives each guarantee a specific worst case complexity and thus allow generic code to be written independently of the container implementation. For example the primitives `c.remove(r)` and `c.linearRemove(r)` both remove the sequence of elements in range `r` from the container `c`. The primitive `c.remove(r)` guarantees $(BIGOH n$(SUBSCRIPT r) log n$(SUBSCRIPT c)) complexity in the worst case and `c.linearRemove(r)` relaxes this guarantee to $(BIGOH n$(SUBSCRIPT c)). Since a sequence of elements can be removed from a $(MREF_ALTTEXT doubly linked list,std,container,dlist) in constant time, `DList` provides the primitive `c.remove(r)` as well as `c.linearRemove(r)`. On the other hand $(MREF_ALTTEXT Array, std,container, array) only offers `c.linearRemove(r)`. The following table describes the common set of primitives that containers implement. A container need not implement all primitives, but if a primitive is implemented, it must support the syntax described in the $(B syntax) column with the semantics described in the $(B description) column, and it must not have a worst-case complexity worse than denoted in big-O notation in the $(BIGOH ·) column. Below, `C` means a container type, `c` is a value of container type, $(D n$(SUBSCRIPT x)) represents the effective length of value `x`, which could be a single element (in which case $(D n$(SUBSCRIPT x)) is `1`), a container, or a range. $(BOOKTABLE Container primitives, $(TR $(TH Syntax) $(TH $(BIGOH ·)) $(TH Description) ) $(TR $(TDNW `C(x)`) $(TDNW $(D n$(SUBSCRIPT x))) $(TD Creates a container of type `C` from either another container or a range. The created container must not be a null reference even if x is empty.) ) $(TR $(TDNW `c.dup`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Returns a duplicate of the container.) ) $(TR $(TDNW $(D c ~ x)) $(TDNW $(D n$(SUBSCRIPT c) + n$(SUBSCRIPT x))) $(TD Returns the concatenation of `c` and `r`. `x` may be a single element or an input range.) ) $(TR $(TDNW $(D x ~ c)) $(TDNW $(D n$(SUBSCRIPT c) + n$(SUBSCRIPT x))) $(TD Returns the concatenation of `x` and `c`. `x` may be a single element or an input range type.) ) $(LEADINGROWN 3, Iteration ) $(TR $(TD `c.Range`) $(TD) $(TD The primary range type associated with the container.) ) $(TR $(TD `c[]`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns a range iterating over the entire container, in a container-defined order.) ) $(TR $(TDNW $(D c[a .. b])) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Fetches a portion of the container from key `a` to key `b`.) ) $(LEADINGROWN 3, Capacity ) $(TR $(TD `c.empty`) $(TD `1`) $(TD Returns `true` if the container has no elements, `false` otherwise.) ) $(TR $(TD `c.length`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns the number of elements in the container.) ) $(TR $(TDNW $(D c.length = n)) $(TDNW $(D n$(SUBSCRIPT c) + n)) $(TD Forces the number of elements in the container to `n`. If the container ends up growing, the added elements are initialized in a container-dependent manner (usually with `T.init`).) ) $(TR $(TD `c.capacity`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns the maximum number of elements that can be stored in the container without triggering a reallocation.) ) $(TR $(TD `c.reserve(x)`) $(TD $(D n$(SUBSCRIPT c))) $(TD Forces `capacity` to at least `x` without reducing it.) ) $(LEADINGROWN 3, Access ) $(TR $(TDNW `c.front`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns the first element of the container, in a container-defined order.) ) $(TR $(TDNW `c.moveFront`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Destructively reads and returns the first element of the container. The slot is not removed from the container; it is left initialized with `T.init`. This routine need not be defined if $(D front) returns a `ref`.) ) $(TR $(TDNW $(D c.front = v)) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Assigns `v` to the first element of the container.) ) $(TR $(TDNW `c.back`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns the last element of the container, in a container-defined order.) ) $(TR $(TDNW `c.moveBack`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Destructively reads and returns the last element of the container. The slot is not removed from the container; it is left initialized with `T.init`. This routine need not be defined if $(D front) returns a `ref`.) ) $(TR $(TDNW $(D c.back = v)) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Assigns `v` to the last element of the container.) ) $(TR $(TDNW `c[x]`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Provides indexed access into the container. The index type is container-defined. A container may define several index types (and consequently overloaded indexing).) ) $(TR $(TDNW `c.moveAt(x)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Destructively reads and returns the value at position `x`. The slot is not removed from the container; it is left initialized with $(D T.init).) ) $(TR $(TDNW $(D c[x] = v)) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Sets element at specified index into the container.) ) $(TR $(TDNW $(D c[x] $(I op)= v)) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Performs read-modify-write operation at specified index into the container.) ) $(LEADINGROWN 3, Operations ) $(TR $(TDNW $(D e in c)) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns nonzero if e is found in `c`.) ) $(TR $(TDNW `c.lowerBound(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns a range of all elements strictly less than `v`.) ) $(TR $(TDNW `c.upperBound(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns a range of all elements strictly greater than `v`.) ) $(TR $(TDNW `c.equalRange(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Returns a range of all elements in `c` that are equal to `v`.) ) $(LEADINGROWN 3, Modifiers ) $(TR $(TDNW $(D c ~= x)) $(TDNW $(D n$(SUBSCRIPT c) + n$(SUBSCRIPT x))) $(TD Appends `x` to `c`. `x` may be a single element or an input range type.) ) $(TR $(TDNW `c.clear()`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Removes all elements in `c`.) ) $(TR $(TDNW `c.insert(x)`) $(TDNW $(D n$(SUBSCRIPT x) * log n$(SUBSCRIPT c))) $(TD Inserts `x` in `c` at a position (or positions) chosen by `c`.) ) $(TR $(TDNW `c.stableInsert(x)`) $(TDNW $(D n$(SUBSCRIPT x) * log n$(SUBSCRIPT c))) $(TD Same as `c.insert(x)`, but is guaranteed to not invalidate any ranges.) ) $(TR $(TDNW `c.linearInsert(v)`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Same as `c.insert(v)` but relaxes complexity to linear.) ) $(TR $(TDNW `c.stableLinearInsert(v)`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Same as `c.stableInsert(v)` but relaxes complexity to linear.) ) $(TR $(TDNW `c.removeAny()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Removes some element from `c` and returns it.) ) $(TR $(TDNW `c.stableRemoveAny()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Same as `c.removeAny()`, but is guaranteed to not invalidate any iterators.) ) $(TR $(TDNW `c.insertFront(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Inserts `v` at the front of `c`.) ) $(TR $(TDNW `c.stableInsertFront(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Same as `c.insertFront(v)`, but guarantees no ranges will be invalidated.) ) $(TR $(TDNW `c.insertBack(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Inserts `v` at the back of `c`.) ) $(TR $(TDNW `c.stableInsertBack(v)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Same as `c.insertBack(v)`, but guarantees no ranges will be invalidated.) ) $(TR $(TDNW `c.removeFront()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Removes the element at the front of `c`.) ) $(TR $(TDNW `c.stableRemoveFront()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Same as `c.removeFront()`, but guarantees no ranges will be invalidated.) ) $(TR $(TDNW `c.removeBack()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Removes the value at the back of `c`.) ) $(TR $(TDNW `c.stableRemoveBack()`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Same as `c.removeBack()`, but guarantees no ranges will be invalidated.) ) $(TR $(TDNW `c.remove(r)`) $(TDNW $(D n$(SUBSCRIPT r) * log n$(SUBSCRIPT c))) $(TD Removes range `r` from `c`.) ) $(TR $(TDNW `c.stableRemove(r)`) $(TDNW $(D n$(SUBSCRIPT r) * log n$(SUBSCRIPT c))) $(TD Same as `c.remove(r)`, but guarantees iterators are not invalidated.) ) $(TR $(TDNW `c.linearRemove(r)`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Removes range `r` from `c`.) ) $(TR $(TDNW `c.stableLinearRemove(r)`) $(TDNW $(D n$(SUBSCRIPT c))) $(TD Same as `c.linearRemove(r)`, but guarantees iterators are not invalidated.) ) $(TR $(TDNW `c.removeKey(k)`) $(TDNW $(D log n$(SUBSCRIPT c))) $(TD Removes an element from `c` by using its key `k`. The key's type is defined by the container.) ) ) Source: $(PHOBOSSRC std/container/package.d) Copyright: Red-black tree code copyright (C) 2008- by Steven Schveighoffer. Other code copyright 2010- Andrei Alexandrescu. All rights reserved by the respective holders. License: Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at $(HTTP boost.org/LICENSE_1_0.txt)). Authors: Steven Schveighoffer, $(HTTP erdani.com, Andrei Alexandrescu) */ module std.container; public import std.container.array; public import std.container.binaryheap; public import std.container.dlist; public import std.container.rbtree; public import std.container.slist; import std.meta; /* The following documentation and type `TotalContainer` are intended for developers only. `TotalContainer` is an unimplemented container that illustrates a host of primitives that a container may define. It is to some extent the bottom of the conceptual container hierarchy. A given container most often will choose to only implement a subset of these primitives, and define its own additional ones. Adhering to the standard primitive names below allows generic code to work independently of containers. Things to remember: any container must be a reference type, whether implemented as a `class` or `struct`. No primitive below requires the container to escape addresses of elements, which means that compliant containers can be defined to use reference counting or other deterministic memory management techniques. A container may choose to define additional specific operations. The only requirement is that those operations bear different names than the ones below, lest user code gets confused. Complexity of operations should be interpreted as "at least as good as". If an operation is required to have $(BIGOH n) complexity, it could have anything lower than that, e.g. $(BIGOH log(n)). Unless specified otherwise, `n` inside a $(BIGOH) expression stands for the number of elements in the container. */ struct TotalContainer(T) { /** If the container has a notion of key-value mapping, `KeyType` defines the type of the key of the container. */ alias KeyType = T; /** If the container has a notion of multikey-value mapping, $(D KeyTypes[k]), where `k` is a zero-based unsigned number, defines the type of the `k`th key of the container. A container may define both `KeyType` and `KeyTypes`, e.g. in the case it has the notion of primary/preferred key. */ alias KeyTypes = AliasSeq!T; /** If the container has a notion of key-value mapping, `ValueType` defines the type of the value of the container. Typically, a map-style container mapping values of type `K` to values of type `V` defines `KeyType` to be `K` and `ValueType` to be `V`. */ alias ValueType = T; /** Defines the container's primary range, which embodies one of the ranges defined in $(MREF std,range). Generally a container may define several types of ranges. */ struct Range { /++ Range primitives. +/ @property bool empty() { assert(0, "Not implemented"); } /// Ditto @property ref T front() //ref return optional { assert(0, "Not implemented"); } /// Ditto @property void front(T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T moveFront() { assert(0, "Not implemented"); } /// Ditto void popFront() { assert(0, "Not implemented"); } /// Ditto @property ref T back() //ref return optional { assert(0, "Not implemented"); } /// Ditto @property void back(T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T moveBack() { assert(0, "Not implemented"); } /// Ditto void popBack() { assert(0, "Not implemented"); } /// Ditto T opIndex(size_t i) //ref return optional { assert(0, "Not implemented"); } /// Ditto void opIndexAssign(size_t i, T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T opIndexUnary(string op)(size_t i) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto void opIndexOpAssign(string op)(size_t i, T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T moveAt(size_t i) { assert(0, "Not implemented"); } /// Ditto @property size_t length() { assert(0, "Not implemented"); } } /** Property returning `true` if and only if the container has no elements. Complexity: $(BIGOH 1) */ @property bool empty() { assert(0, "Not implemented"); } /** Returns a duplicate of the container. The elements themselves are not transitively duplicated. Complexity: $(BIGOH n). */ @property TotalContainer dup() { assert(0, "Not implemented"); } /** Returns the number of elements in the container. Complexity: $(BIGOH log(n)). */ @property size_t length() { assert(0, "Not implemented"); } /** Returns the maximum number of elements the container can store without (a) allocating memory, (b) invalidating iterators upon insertion. Complexity: $(BIGOH log(n)). */ @property size_t capacity() { assert(0, "Not implemented"); } /** Ensures sufficient capacity to accommodate `n` elements. Postcondition: $(D capacity >= n) Complexity: $(BIGOH log(e - capacity)) if $(D e > capacity), otherwise $(BIGOH 1). */ void reserve(size_t e) { assert(0, "Not implemented"); } /** Returns a range that iterates over all elements of the container, in a container-defined order. The container should choose the most convenient and fast method of iteration for `opSlice()`. Complexity: $(BIGOH log(n)) */ Range opSlice() { assert(0, "Not implemented"); } /** Returns a range that iterates the container between two specified positions. Complexity: $(BIGOH log(n)) */ Range opSlice(size_t a, size_t b) { assert(0, "Not implemented"); } /** Forward to `opSlice().front` and `opSlice().back`, respectively. Complexity: $(BIGOH log(n)) */ @property ref T front() //ref return optional { assert(0, "Not implemented"); } /// Ditto @property void front(T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T moveFront() { assert(0, "Not implemented"); } /// Ditto @property ref T back() //ref return optional { assert(0, "Not implemented"); } /// Ditto @property void back(T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// Ditto T moveBack() { assert(0, "Not implemented"); } /** Indexing operators yield or modify the value at a specified index. */ ref T opIndex(KeyType) //ref return optional { assert(0, "Not implemented"); } /// ditto void opIndexAssign(KeyType i, T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// ditto T opIndexUnary(string op)(KeyType i) //Only when front does not return by ref { assert(0, "Not implemented"); } /// ditto void opIndexOpAssign(string op)(KeyType i, T value) //Only when front does not return by ref { assert(0, "Not implemented"); } /// ditto T moveAt(KeyType i) { assert(0, "Not implemented"); } /** $(D k in container) returns true if the given key is in the container. */ bool opBinaryRight(string op)(KeyType k) if (op == "in") { assert(0, "Not implemented"); } /** Returns a range of all elements containing `k` (could be empty or a singleton range). */ Range equalRange(KeyType k) { assert(0, "Not implemented"); } /** Returns a range of all elements with keys less than `k` (could be empty or a singleton range). Only defined by containers that store data sorted at all times. */ Range lowerBound(KeyType k) { assert(0, "Not implemented"); } /** Returns a range of all elements with keys larger than `k` (could be empty or a singleton range). Only defined by containers that store data sorted at all times. */ Range upperBound(KeyType k) { assert(0, "Not implemented"); } /** Returns a new container that's the concatenation of `this` and its argument. `opBinaryRight` is only defined if `Stuff` does not define `opBinary`. Complexity: $(BIGOH n + m), where m is the number of elements in $(D stuff) */ TotalContainer opBinary(string op)(Stuff rhs) if (op == "~") { assert(0, "Not implemented"); } /// ditto TotalContainer opBinaryRight(string op)(Stuff lhs) if (op == "~") { assert(0, "Not implemented"); } /** Forwards to $(D insertAfter(this[], stuff)). */ void opOpAssign(string op)(Stuff stuff) if (op == "~") { assert(0, "Not implemented"); } /** Removes all contents from the container. The container decides how $(D capacity) is affected. Postcondition: `empty` Complexity: $(BIGOH n) */ void clear() { assert(0, "Not implemented"); } /** Sets the number of elements in the container to `newSize`. If $(D newSize) is greater than `length`, the added elements are added to unspecified positions in the container and initialized with $(D .init). Complexity: $(BIGOH abs(n - newLength)) Postcondition: $(D _length == newLength) */ @property void length(size_t newLength) { assert(0, "Not implemented"); } /** Inserts `stuff` in an unspecified position in the container. Implementations should choose whichever insertion means is the most advantageous for the container, but document the exact behavior. `stuff` can be a value convertible to the element type of the container, or a range of values convertible to it. The `stable` version guarantees that ranges iterating over the container are never invalidated. Client code that counts on non-invalidating insertion should use `stableInsert`. Such code would not compile against containers that don't support it. Returns: The number of elements added. Complexity: $(BIGOH m * log(n)), where `m` is the number of elements in `stuff` */ size_t insert(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } ///ditto size_t stableInsert(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } /** Same as `insert(stuff)` and `stableInsert(stuff)` respectively, but relax the complexity constraint to linear. */ size_t linearInsert(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } ///ditto size_t stableLinearInsert(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } /** Picks one value in an unspecified position in the container, removes it from the container, and returns it. Implementations should pick the value that's the most advantageous for the container. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. Precondition: `!empty` Returns: The element removed. Complexity: $(BIGOH log(n)). */ T removeAny() { assert(0, "Not implemented"); } /// ditto T stableRemoveAny() { assert(0, "Not implemented"); } /** Inserts `value` to the front or back of the container. `stuff` can be a value convertible to the container's element type or a range of values convertible to it. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. Returns: The number of elements inserted Complexity: $(BIGOH log(n)). */ size_t insertFront(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t stableInsertFront(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t insertBack(Stuff)(Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t stableInsertBack(T value) { assert(0, "Not implemented"); } /** Removes the value at the front or back of the container. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. The optional parameter $(D howMany) instructs removal of that many elements. If $(D howMany > n), all elements are removed and no exception is thrown. Precondition: `!empty` Complexity: $(BIGOH log(n)). */ void removeFront() { assert(0, "Not implemented"); } /// ditto void stableRemoveFront() { assert(0, "Not implemented"); } /// ditto void removeBack() { assert(0, "Not implemented"); } /// ditto void stableRemoveBack() { assert(0, "Not implemented"); } /** Removes `howMany` values at the front or back of the container. Unlike the unparameterized versions above, these functions do not throw if they could not remove `howMany` elements. Instead, if $(D howMany > n), all elements are removed. The returned value is the effective number of elements removed. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. Returns: The number of elements removed Complexity: $(BIGOH howMany * log(n)). */ size_t removeFront(size_t howMany) { assert(0, "Not implemented"); } /// ditto size_t stableRemoveFront(size_t howMany) { assert(0, "Not implemented"); } /// ditto size_t removeBack(size_t howMany) { assert(0, "Not implemented"); } /// ditto size_t stableRemoveBack(size_t howMany) { assert(0, "Not implemented"); } /** Removes all values corresponding to key `k`. Complexity: $(BIGOH m * log(n)), where `m` is the number of elements with the same key. Returns: The number of elements removed. */ size_t removeKey(KeyType k) { assert(0, "Not implemented"); } /** Inserts `stuff` before, after, or instead range `r`, which must be a valid range previously extracted from this container. `stuff` can be a value convertible to the container's element type or a range of objects convertible to it. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. Returns: The number of values inserted. Complexity: $(BIGOH n + m), where `m` is the length of `stuff` */ size_t insertBefore(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t stableInsertBefore(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t insertAfter(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t stableInsertAfter(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t replace(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /// ditto size_t stableReplace(Stuff)(Range r, Stuff stuff) { assert(0, "Not implemented"); } /** Removes all elements belonging to `r`, which must be a range obtained originally from this container. The stable version behaves the same, but guarantees that ranges iterating over the container are never invalidated. Returns: A range spanning the remaining elements in the container that initially were right after `r`. Complexity: $(BIGOH m * log(n)), where `m` is the number of elements in `r` */ Range remove(Range r) { assert(0, "Not implemented"); } /// ditto Range stableRemove(Range r) { assert(0, "Not implemented"); } /** Same as `remove` above, but has complexity relaxed to linear. Returns: A range spanning the remaining elements in the container that initially were right after `r`. Complexity: $(BIGOH n) */ Range linearRemove(Range r) { assert(0, "Not implemented"); } /// ditto Range stableLinearRemove(Range r) { assert(0, "Not implemented"); } } @safe unittest { TotalContainer!int test; }