Fix #232 for Array

Because const is transitive, if we create a range as Range!(const E)
there is no way to get the original type from inside of the range. So if
E is int*, the original type of const(E) could be const(int)* or int*.
Unqual!(const(int*)) returns const(int)*. So pass the whole container as
template parameter. It is a breaking change but since we have Range and
ConstRange aliases now, the usage should be fine.
This commit is contained in:
Eugen Wissner 2017-07-04 07:24:29 +02:00
parent e46e45ad5a
commit 4fd37e84f8

View File

@ -26,13 +26,13 @@ import tanya.memory;
* Random-access range for the $(D_PSYMBOL Array). * Random-access range for the $(D_PSYMBOL Array).
* *
* Params: * Params:
* E = Element type. * A = Array type.
*/ */
struct Range(E) struct Range(A)
{ {
private alias E = PointerTarget!(typeof(A.data));
private E* begin, end; private E* begin, end;
private alias ContainerType = CopyConstness!(E, Array!(Unqual!E)); private A* container;
private ContainerType* container;
invariant invariant
{ {
@ -42,7 +42,7 @@ struct Range(E)
assert(this.end <= this.container.data + this.container.length); assert(this.end <= this.container.data + this.container.length);
} }
private this(ref ContainerType container, E* begin, E* end) @trusted private this(ref A container, E* begin, E* end) @trusted
in in
{ {
assert(begin <= end); assert(begin <= end);
@ -130,7 +130,7 @@ struct Range(E)
return typeof(return)(*this.container, this.begin, this.end); return typeof(return)(*this.container, this.begin, this.end);
} }
Range!(const E) opIndex() const Range!(const A) opIndex() const
{ {
return typeof(return)(*this.container, this.begin, this.end); return typeof(return)(*this.container, this.begin, this.end);
} }
@ -146,7 +146,7 @@ struct Range(E)
return typeof(return)(*this.container, this.begin + i, this.begin + j); return typeof(return)(*this.container, this.begin + i, this.begin + j);
} }
Range!(const E) opSlice(const size_t i, const size_t j) const @trusted Range!(const A) opSlice(const size_t i, const size_t j) const @trusted
in in
{ {
assert(i <= j); assert(i <= j);
@ -172,10 +172,10 @@ struct Range(E)
struct Array(T) struct Array(T)
{ {
/// The range types for $(D_PSYMBOL Array). /// The range types for $(D_PSYMBOL Array).
alias Range = .Range!T; alias Range = .Range!Array;
/// Ditto. /// Ditto.
alias ConstRange = .Range!(const T); alias ConstRange = .Range!(const Array);
private size_t length_; private size_t length_;
private T* data; private T* data;
@ -651,9 +651,9 @@ struct Array(T)
body body
{ {
auto end = this.data + this.length; auto end = this.data + this.length;
moveAll(.Range!T(this, r.end, end), .Range!T(this, r.begin, end)); moveAll(Range(this, r.end, end), Range(this, r.begin, end));
length = length - r.length; length = length - r.length;
return .Range!T(this, r.begin, this.data + length); return Range(this, r.begin, this.data + length);
} }
/// ///
@ -863,7 +863,7 @@ struct Array(T)
} }
body body
{ {
return insertAfter(.Range!T(this, this.data, r.begin), el); return insertAfter(Range(this, this.data, r.begin), el);
} }
/// Ditto. /// Ditto.
@ -1617,6 +1617,9 @@ private unittest
} }
A a1, a2; A a1, a2;
auto v1 = Array!A([a1, a2]); auto v1 = Array!A([a1, a2]);
// Issue 232: https://issues.caraus.io/issues/232.
static assert(is(Array!(A*)));
} }
private @safe @nogc unittest private @safe @nogc unittest