C++23 was supposed to fix issues around range-based for
loops. The C++ standard now has wording that I can trace to p2718r0, including the following example at the end of the section "The range-based for statement [stmt.ranged]
" (note the undefined behavior
comment:
using T = std::list<int>; const T& f1(const T& t) { return t; } const T& f2(T t) { return t; } T g(); void foo() { for (auto e : f1(g())) {} // OK, lifetime of return value of g() extended for (auto e : f2(g())) {} // undefined behavior }
Let's say I write a coroutine using the C++23 std::generator
that takes an argument by value i.e. following C++ core guidelines rule CP.53: Parameters to coroutines should not be passed by reference:
#include <generator> #include <string> #include <iostream> std::generator<std::string> generator_f(std::string x) { co_yield x; } std::string sample_g() { return "abc"; } int main() { for(const auto& elem: generator_f(sample_g())) { std::cout << elem << "\n"; } return 0; }
I assume that based on the example in the C++ standard, the code in the for
loop in main()
above is undefined behavior.
What's the rationale behind the undefined behavior rule illustrated by the example in the C++ standard? The downside is that it makes error prone the usage of a std::generator
with arguments in a for
loop (which is where you would want to use a generator, i.e. not really fixing lifetime problems with range-based for
statements).