Hi all,
Recently I am starting to use library, and I met an unexpected behavior of my program, after debugging I found it was caused by std::views::transform, when it along with other std::views::*, the lambda of transform will get invoked every time the latter view iterators get dereferenced. For explanation, here is an example:
#include <print>
#include <ranges>
auto main() -> int {
auto v = std::views::iota(0, 3) |
std::views::transform([](auto const &i) {
std::print("Lambda 1 [{}] --> ", i);
return i;
}) |
std::views::filter([](auto const &_i) {
std::print("Lambda 2 --> ");
return true;
}) |
std::views::transform([](auto const &i) {
std::print("Lambda 3 --> ");
return i; });
for (auto const &i : v) {
std::println("{}", i);
}
return 0;
}
In my understanding, the lambda 1 should only be called once every round of elements process, but the actual output is:
Lambda 1 [0] --> Lambda 2 --> Lambda 1 [0] --> Lambda 3 --> 0
Lambda 1 [1] --> Lambda 2 --> Lambda 1 [1] --> Lambda 3 --> 1
Lambda 1 [2] --> Lambda 2 --> Lambda 1 [2] --> Lambda 3 --> 2
I admit this is a little bit counter-intuitive for me. I have thought there would be some internal ‘cache’ inside of the views::transform to avoid repetitive invocation, but I also know this would incur space waste (maybe it is more reasonable just for forward_iterator?). So I am wondering what the expected behavior is from pros/standard committees’ perspective, and how to write right program in line with programmer’s expectation using std::ranges. I am all ears.
Thank you.