Opened 9 years ago
Closed 8 years ago
#9851 closed Bugs (fixed)
Iterators from rang have different category than the range
Reported by: | anonymous | Owned by: | Neil Groves |
---|---|---|---|
Milestone: | Boost 1.56.0 | Component: | range |
Version: | Boost 1.55.0 | Severity: | Problem |
Keywords: | Cc: |
Description
According to the documentation for transformed, the category is single pass, which means that it should be safe to include side effects in the function used:
int main() { int transformed_called = 0, filtered_called = 0; vector<int> a{ 1, 2, 3 }; auto b = (a | transformed([&](int aa) { ++transformed_called; return aa + 1; }) | filtered([&](int aa) { ++filtered_called; return aa < 4; })); auto c = vector<int>(b::begin(b), b::end(b)); cout << transformed_called << ", " << filtered_called << endl; return 0; }
However, the output of this program is "5, 3" instead of the expected "3, 3", which means that the iterators returned by begin() and end() are forward iterators. I guess they should be input iterators (single pass) instead?
Change History (9)
follow-up: 2 comment:1 by , 9 years ago
comment:2 by , 8 years ago
Replying to anonymous:
Strangely, removing the line
auto c = vector<int>(b::begin(b), b::end(b));results in the output "1, 1" instead of "0, 0", so it seems like merely chaining together adaptors causes the functions to be called. Perhaps the problem is caused by something other than iterator categories after all.
This is because range adaptors are applied lazily. Therefore the change in invocation counts is correct behaviour.
follow-up: 6 comment:3 by , 8 years ago
Status: | new → assigned |
---|
The reason you originally get 5,3 as a result is because the Filtered adaptor requires a ForwardPassRange since it needs to check adjacent elements.
Your code snippet is legal since it isn't a single-pass range as the input. Passing a genuine SinglePassRange to an adaptor requiring a ForwardRange will typically trigger a compile-time error with a Concept Assert. Having looked through the code I can see that I should add some more concept assert statements to ensure invalid code fails to compile.
comment:4 by , 8 years ago
Concept checking has been added to all of the Boost.Range adaptors. I have added 24 compilation failure unit tests to cover adaptors that require more than a SinglePassRange.
I'll watch the unit tests on develop for a few cycles and merge to master when the release cycle allows.
comment:5 by , 8 years ago
Milestone: | To Be Determined → Boost 1.57.0 |
---|
comment:6 by , 8 years ago
Your code snippet is legal since it isn't a single-pass range as the input.
Isn't the input to filtered the output from transformed? The documentation for transformed says the range category is single-pass. Wouldn't that make my code snippet illegal?
comment:7 by , 8 years ago
Yes it does make it illegal. This is what I was thinking, but not what I wrote in my previous comment! I meant that the code snippet was illegal. This was why I was mentioning that I ought to make the error more obvious at compile-time with Concept Assertions.
I'm sorry I messed up my comment previously. I'll merge the change in when this is allowed by the Boost release cycle.
comment:8 by , 8 years ago
Milestone: | Boost 1.57.0 → Boost 1.56.0 |
---|
Release window for 1.56 has been extended so I can put this into 1.56.
comment:9 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Merged to master and ready for release 1.56.
Strangely, removing the line
results in the output "1, 1" instead of "0, 0", so it seems like merely chaining together adaptors causes the functions to be called. Perhaps the problem is caused by something other than iterator categories after all.