Is it defined behavior to combine a transformation that creates objects with a transformation that extracts attributes from these objects by constant reference? The following code does not work as expected in Visual Studio 16.10.2, but it seems to work with gcc 11.1.
#include <array>
#include <iostream>
#include <ranges>
#include <string>
struct A {
std::string s;
};
int main() {
auto values = std::array{"a", "b"};
// transform 1: create objects
auto objects = values | std::views::transform(
[](const auto& s) { return A{s}; }
);
// transform 2: access object attributes
auto lambdaReturningConstRef = [](const auto& a) -> const auto& { return a.s; };
auto result = objects | std::views::transform(lambdaReturningConstRef);
for (const auto& s : result) {
std::cout << s << " ";
}
}
The expected output is "a b", but the actual output with Visual Studio is empty. Also, in a clean Release build (but not in Debug), I get a warning C4172 about returning the address of a local variable or temporary.
Adding a getter in A returning a constant reference and using std::mem_fn instead of the lambda removes the warning entirely, but still does not produce the expected result. Same for using &A::s instead of the lambda.
Removing the explicit return type from the lambda obviously fixes the issue.