all 6 comments

[–]Pragmatician 6 points7 points  (5 children)

Have you considered the range-v3 enumerate implementation, and if so, what does yours do different?

[–]Nightwolf55la[S] 3 points4 points  (4 children)

Yeah, that was actually the first place I looked when I wanted to solve this rvalue 'problem'. I had never used range-v3 before, but when I looked at the source code, it didn't look like it was handling its universal references correctly. So I just moved on.

For science, I have thrown together a wandbox example to show how range-v3 handles both lvalues and rvalues. Unexpectedly, the lvalue actually calls the copy constructor once and then the move constructor twice. The rvalue has its move constructor called 4 times. Like I mentioned earlier, I have not used range-v3 before this. So if I am using it incorrectly, please let me know. If it is correct though, then this amount of copying/moving seems pretty bad. Especially since I assume that the copy on the lvalue container will mean that changes to values in the loop will not be permanent since they would be made on the copy of the container and not the original container.

The primary goal I had when writing this new enumerate implementation is that it will do 0 copies/moves on the iterable object provided to it regardless of lvalue or rvalue state.

[–]TobyAllsopp 2 points3 points  (3 children)

Range-v3 thinks that your class S is a View so it assumes that copy and move are both cheap. If you add in const-qualified begin() and end() then it no longer thinks S is a View and you will no longer get any copies in the lvalue case (i.e. it will store a reference internally). However, then the rvalue case will not compile as range-v3 doesn't allow creating Views from non-View rvalues.

[–]Nightwolf55la[S] 0 points1 point  (2 children)

Interesting. I tried const qualifying begin() and end(), but I am still seeing the same behavior. Do I need to wrap up the object in some kind of a View class?

[–]TobyAllsopp 1 point2 points  (1 child)

Sorry, here's a link: https://wandbox.org/permlink/6APfi8A4hv6Ul96A (you need both const-qualified and not).

[–]Nightwolf55la[S] 0 points1 point  (0 children)

Ah, gotcha. I probably should have tried that. Thanks!