Add SList.opAssign
This commit is contained in:
parent
4d8b95812e
commit
aabb4fb534
@ -356,18 +356,17 @@ struct SList(T)
|
|||||||
size_t retLength;
|
size_t retLength;
|
||||||
Entry* next, newHead;
|
Entry* next, newHead;
|
||||||
|
|
||||||
|
if (!el.empty)
|
||||||
|
{
|
||||||
|
next = allocator.make!Entry(el.front);
|
||||||
|
newHead = next;
|
||||||
|
el.popFront();
|
||||||
|
retLength = 1;
|
||||||
|
}
|
||||||
foreach (ref e; el)
|
foreach (ref e; el)
|
||||||
{
|
{
|
||||||
if (next is null)
|
next.next = allocator.make!Entry(e);
|
||||||
{
|
next = next.next;
|
||||||
next = allocator.make!Entry(e);
|
|
||||||
newHead = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
next.next = allocator.make!Entry(e);
|
|
||||||
next = next.next;
|
|
||||||
}
|
|
||||||
++retLength;
|
++retLength;
|
||||||
}
|
}
|
||||||
if (newHead !is null)
|
if (newHead !is null)
|
||||||
@ -406,13 +405,16 @@ struct SList(T)
|
|||||||
assert(l2.front == 9);
|
assert(l2.front == 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool checkRangeBelonging(ref Range!Entry r) const
|
version (assert)
|
||||||
{
|
{
|
||||||
const(Entry*)* pos;
|
private bool checkRangeBelonging(ref Range!Entry r) const
|
||||||
for (pos = &head; pos != r.head && *pos !is null; pos = &(*pos).next)
|
|
||||||
{
|
{
|
||||||
|
const(Entry*)* pos;
|
||||||
|
for (pos = &head; pos != r.head && *pos !is null; pos = &(*pos).next)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return pos == r.head;
|
||||||
}
|
}
|
||||||
return pos == r.head;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -741,16 +743,116 @@ struct SList(T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns: Range that iterates over all elements of the container, in
|
||||||
|
* forward order.
|
||||||
|
*/
|
||||||
Range!Entry opIndex()
|
Range!Entry opIndex()
|
||||||
{
|
{
|
||||||
return typeof(return)(head);
|
return typeof(return)(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
Range!(const Entry) opIndex() const
|
Range!(const Entry) opIndex() const
|
||||||
{
|
{
|
||||||
return typeof(return)(head);
|
return typeof(return)(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns another list.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM that) is passed by value, it won't be copied, but moved.
|
||||||
|
* This list will take the ownership over $(D_PARAM that)'s storage and
|
||||||
|
* the allocator.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM that) is passed by reference, it will be copied.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Content type.
|
||||||
|
* that = The value should be assigned.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref typeof(this) opAssign(R)(const ref R that)
|
||||||
|
if (is(Unqual!R == SList))
|
||||||
|
{
|
||||||
|
return this = that[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ditto.
|
||||||
|
ref typeof(this) opAssign(R)(const ref R that)
|
||||||
|
if (is(Unqual!R == SList))
|
||||||
|
{
|
||||||
|
swap(this.head, that.head);
|
||||||
|
swap(this.allocator_, that.allocator_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns an input range.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Type of the initial range.
|
||||||
|
* that = Values to initialize the list with.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref typeof(this) opAssign(R)(R that) @trusted
|
||||||
|
if (!isInfinite!R
|
||||||
|
&& isInputRange!R
|
||||||
|
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||||
|
{
|
||||||
|
Entry** next = &head;
|
||||||
|
|
||||||
|
foreach (ref e; that)
|
||||||
|
{
|
||||||
|
if (*next is null)
|
||||||
|
{
|
||||||
|
*next = allocator.make!Entry(e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*next).content = e;
|
||||||
|
}
|
||||||
|
next = &(*next).next;
|
||||||
|
}
|
||||||
|
remove(Range!Entry(*next));
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe @nogc unittest
|
||||||
|
{
|
||||||
|
auto l1 = SList!int([5, 4, 9]);
|
||||||
|
auto l2 = SList!int([9, 4]);
|
||||||
|
l1 = l2[];
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a static array.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Static array size.
|
||||||
|
* that = Values to initialize the vector with.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref typeof(this) opAssign(size_t R)(T[R] that)
|
||||||
|
{
|
||||||
|
return opAssign!(T[])(that[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe @nogc unittest
|
||||||
|
{
|
||||||
|
auto l1 = SList!int([5, 4, 9]);
|
||||||
|
auto l2 = SList!int([9, 4]);
|
||||||
|
l1 = [9, 4];
|
||||||
|
assert(l1 == l2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mixin DefaultAllocator;
|
mixin DefaultAllocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,11 +221,29 @@ struct Vector(T)
|
|||||||
if (is(R == Vector))
|
if (is(R == Vector))
|
||||||
{
|
{
|
||||||
this(allocator);
|
this(allocator);
|
||||||
moveAssign(init);
|
if (allocator is init.allocator)
|
||||||
|
{
|
||||||
|
// Just steal all references and the allocator.
|
||||||
|
vector = init.vector;
|
||||||
|
length_ = init.length_;
|
||||||
|
capacity_ = init.capacity_;
|
||||||
|
|
||||||
|
// Reset the source vector, so it can't destroy the moved storage.
|
||||||
|
init.length_ = init.capacity_ = 0;
|
||||||
|
init.vector = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Move each element.
|
||||||
|
reserve(init.length);
|
||||||
|
moveEmplaceAll(init.vector[0 .. init.length_], vector[0 .. init.length_]);
|
||||||
|
length_ = init.length;
|
||||||
|
// Destructor of init should destroy it here.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
unittest
|
@trusted @nogc unittest
|
||||||
{
|
{
|
||||||
auto v1 = Vector!int([1, 2, 3]);
|
auto v1 = Vector!int([1, 2, 3]);
|
||||||
auto v2 = Vector!int(v1);
|
auto v2 = Vector!int(v1);
|
||||||
@ -238,7 +256,7 @@ struct Vector(T)
|
|||||||
assert(v3.capacity == 3);
|
assert(v3.capacity == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest // const constructor tests
|
private @trusted @nogc unittest // const constructor tests
|
||||||
{
|
{
|
||||||
auto v1 = const Vector!int([1, 2, 3]);
|
auto v1 = const Vector!int([1, 2, 3]);
|
||||||
auto v2 = Vector!int(v1);
|
auto v2 = Vector!int(v1);
|
||||||
@ -1455,58 +1473,54 @@ struct Vector(T)
|
|||||||
assert(data.length == 1);
|
assert(data.length == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void moveAssign(ref Vector v) @trusted
|
|
||||||
{
|
|
||||||
if (allocator is v.allocator)
|
|
||||||
{
|
|
||||||
// Just steal all references and the allocator.
|
|
||||||
vector = v.vector;
|
|
||||||
length_ = v.length_;
|
|
||||||
capacity_ = v.capacity_;
|
|
||||||
|
|
||||||
// Reset the source vector, so it can't destroy the moved storage.
|
|
||||||
v.length_ = v.capacity_ = 0;
|
|
||||||
v.vector = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move each element.
|
|
||||||
reserve(v.length);
|
|
||||||
moveEmplaceAll(v.vector[0 .. v.length_], vector[0 .. v.length_]);
|
|
||||||
length_ = v.length;
|
|
||||||
// Destructor of v should destroy it here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns content to the vector.
|
* Assigns another vector.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM that) is passed by value, it won't be copied, but moved.
|
||||||
|
* This vector will take the ownership over $(D_PARAM that)'s storage and
|
||||||
|
* the allocator.
|
||||||
|
*
|
||||||
|
* If $(D_PARAM that) is passed by reference, it will be copied.
|
||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* R = Content type.
|
* R = Content type.
|
||||||
* init = The value should be assigned.
|
* that = The value should be assigned.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
*/
|
*/
|
||||||
ref typeof(this) opAssign(R)(const ref R init)
|
ref typeof(this) opAssign(R)(const ref R that)
|
||||||
if (is(Unqual!R == Vector))
|
if (is(Unqual!R == Vector))
|
||||||
{
|
{
|
||||||
insertBack(init[]);
|
return this = that[];
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/// Ditto.
|
||||||
ref typeof(this) opAssign(R)(R init)
|
ref typeof(this) opAssign(R)(R that) @trusted
|
||||||
if (is(R == Vector))
|
if (is(R == Vector))
|
||||||
{
|
{
|
||||||
moveAssign(init);
|
swap(this.vector, that.vector);
|
||||||
|
swap(this.length_, that.length_);
|
||||||
|
swap(this.capacity_, that.capacity_);
|
||||||
|
swap(this.allocator_, that.allocator_);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ditto.
|
/**
|
||||||
ref typeof(this) opAssign(R)(R init)
|
* Assigns a range to the vector.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* R = Content type.
|
||||||
|
* that = The value should be assigned.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
|
*/
|
||||||
|
ref typeof(this) opAssign(R)(R that)
|
||||||
if (!isInfinite!R
|
if (!isInfinite!R
|
||||||
&& isInputRange!R
|
&& isInputRange!R
|
||||||
&& isImplicitlyConvertible!(ElementType!R, T))
|
&& isImplicitlyConvertible!(ElementType!R, T))
|
||||||
{
|
{
|
||||||
insertBack(init);
|
this.length = 0;
|
||||||
|
insertBack(that);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1540,12 +1554,13 @@ struct Vector(T)
|
|||||||
*
|
*
|
||||||
* Params:
|
* Params:
|
||||||
* R = Static array size.
|
* R = Static array size.
|
||||||
* init = Values to initialize the vector with.
|
* that = Values to initialize the vector with.
|
||||||
|
*
|
||||||
|
* Returns: $(D_KEYWORD this).
|
||||||
*/
|
*/
|
||||||
ref typeof(this) opAssign(size_t R)(T[R] init)
|
ref typeof(this) opAssign(size_t R)(T[R] that)
|
||||||
{
|
{
|
||||||
insertBack!(T[])(init[]);
|
return opAssign!(T[])(that[]);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user