digitalmars.D.learn - Rewriting a c++ template to D (replacing iterator with ranges
- aliak (37/37) Jan 26 2018 It basically steps through in a stride and sets the checkpoints
- aliak (6/12) Jan 26 2018 Oops, this should be:
- Meta (4/10) Jan 26 2018 Where did you see this? That's got to be some very old code; I
- aliak (5/17) Jan 26 2018 Seems to occur in
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (7/25) Jan 26 2018 The function is called fill, and assigns a value to every element
- aliak (2/8) Jan 27 2018 I see. Yes that makes sense. Thank you.
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (55/92) Jan 26 2018 what is N here? You're declaring it to be an int value in the
- aliak (7/45) Jan 26 2018 Oops again :) Should've been typename N (where N is some integral
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; } } 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; } } I have a more specific question too: 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? 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? Cheers
Jan 26 2018
On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote:range.front = false; while (!range.empty) { range.popFrontN(N); range.front = false; } }Oops, this should be: while (!range.empty) { range.front = false; range.popFrontN(N); }
Jan 26 2018
On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote: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?Where did you see this? That's got to be some very old code; I can't think of any instance where you would not want to use `hasAssignableElements` instead.
Jan 26 2018
On Friday, 26 January 2018 at 14:35:25 UTC, Meta wrote:On Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote:Seems to occur in https://github.com/dlang/phobos/blob/v2.078.1/std/algorithm/mutation.d eg: https://github.com/dlang/phobos/blob/v2.078.1/std/algorithm/mutation.d#L5551) 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?Where did you see this? That's got to be some very old code; I can't think of any instance where you would not want to use `hasAssignableElements` instead.
Jan 26 2018
On Friday, 26 January 2018 at 15:33:03 UTC, aliak wrote:On Friday, 26 January 2018 at 14:35:25 UTC, Meta wrote:The function is called fill, and assigns a value to every element in the range. If a[0] = false compiles, we also want a.fill(false) to compile. It's simply testing that, rather than caring about the exact type of the elements. -- SimenOn Friday, 26 January 2018 at 14:16:04 UTC, aliak wrote:Seems to occur in https://github.com/dlang/phobos/blob/v2.078.1/std/algorithm/mutation.d eg: https://github.com/dlang/phobos/blob/v2.078.1/std/algorithm/mutation.d#L5551) 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?Where did you see this? That's got to be some very old code; I can't think of any instance where you would not want to use `hasAssignableElements` instead.
Jan 26 2018
On Friday, 26 January 2018 at 23:15:41 UTC, Simen Kjærås wrote:The function is called fill, and assigns a value to every element in the range. If a[0] = false compiles, we also want a.fill(false) to compile. It's simply testing that, rather than caring about the exact type of the elements. -- SimenI see. Yes that makes sense. Thank you.
Jan 27 2018
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
Jan 26 2018
On Friday, 26 January 2018 at 14:59:09 UTC, Simen Kjærås wrote: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.Oops again :) Should've been typename N (where N is some integral type).Not exactly. range.front will assert after the last popFrontN (since the range is empty).Ya, sorry, realized this a bit after I posted.It's trying to combine 3 and 4 I think, but it fails because this is allowed in D: int a; a = false;Ah true, so it's more of a is(ElementType!R : bool) check?You'll want to pass the range as ref. hasLvalueElements checks if the elements have lvalue semanticsDoh, of course. It's in the name even!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. -- SimenThanks for the input!
Jan 26 2018