On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote:
It basically steps through in a stride and sets the checkpoints
to false.
C++:
template <typename /*RandomAccessIterator*/ It, int /*Integer*/
N>
void mark(It begin, It end, N step) {
assert(begin != end)
*begin = false;
while (end - begin > step) {
begin = begin + step;
*begin = false;
}
}
what is N here? You're declaring it to be an int value in the
template<> definition, and then use it as a type in the function
definition.
For D this is what I figured would be the way?
void mark(R, N)(auto ref R range, N step)
if (
/* 1 */ isIntegral!N
/* 2 */ && isRandomAccessRange!R
/* 3 */ && is(ElementType!R == bool)
/* 4 */ && hasAssignableElements!R
) {
range.front = false;
while (!range.empty) {
range.popFrontN(N);
range.front = false;
}
}
Not exactly. range.front will assert after the last popFrontN
(since the range is empty).
You'll need something like this:
void main(R, N)(R range, N step)
if (isIntegral!N &&
isRandomAccessRange!R &&
is(ElementType!R == bool) &&
hasAssignableElements!R)
{
if (range.empty) return;
do
{
range.front = false;
range.popFrontN(N);
} while (!range.empty);
}
1) I've seen some phobos code checking for assignability like
this:
is(typeof(range.front = false))
... is that an advantage of that over hasAssignableElements? Or
is that just basically combining constraints 3 and 4 which I
have above?
It's trying to combine 3 and 4 I think, but it fails because this
is allowed in D:
int a;
a = false;
2) Say I wanted to restrict to only lvalue ranges passed in as
inputs. Does that mean I use hasLvalueElements as a constraint
or is remove the "auto" and just have a ref parameter
sufficient?
You'll want to pass the range as ref. hasLvalueElements checks if
the elements have lvalue semantics, not if the range itself does.
Here's a range that has lvalue elements, for which passing it as
ref or non-ref makes a huge difference:
import std.range;
struct R {
int[3] elements;
int index;
ref auto front() {
return elements[index];
}
void popFront() {
++index;
}
bool empty() {
return index >= elements.length;
}
}
unittest {
assert(hasLvalueElements!(R));
auto a = R([1,2,3], 0);
auto b = a;
b.front = 4;
assert(a.elements == [1,2,3]);
assert(b.elements == [4,2,3]);
}
As we can see, b is a complete copy of a, and changing b does not
change a. The exact same behavior would occur if a was passed by
value to a function.
--
Simen