Date: Tue, 17 Jun 2025 07:55:37 +0800 (CST)
It is intuitively assumed that zip_view steps iterators in some consistent order. The following program demonstrates a typical use case: https://godbolt.org/z/7M3bx9o3d
#include<ranges>
#include<sstream>
#include<print>
int main()
{
namespace views = std::views;
auto input = std::istringstream("1 2 3 4 5 6");
for (auto [i, j] : views::zip(views::istream<int>(input), views::istream<int>(input)))
std::print("({}, {}), ", i, j);
std::println();
auto input2 = std::istringstream("a 1 b 2 c 3");
for (auto [i, j] : views::zip(views::istream<char>(input2), views::istream<int>(input2)))
std::print("({}, {}), ", i, j);
}
However, g++ produces unexpected results:
First loop outputs (2, 1), (3, 4), (5, 6)
Second loop outputs nothing
The istream_view bound to a stream sets failbit on invalid input (e.g., reading 'a' as int), halting subsequent operations.
While the evaluation order of arguments of a function call is unspecified, leading to non-portable behavior,
enforcing an order that is consistent between
tuple-transform and tuple-for-each does no hurt.
Microsoft STL already implements tuple-transform by std::tuple{...}instead of std::tuple(...).
Maybe an LWG issue is in needed to specify left-to-right evaluation order for iterator constructions (begin()/end()) and iterator advancements (operator++) in zip_view and related adaptors.
#include<ranges>
#include<sstream>
#include<print>
int main()
{
namespace views = std::views;
auto input = std::istringstream("1 2 3 4 5 6");
for (auto [i, j] : views::zip(views::istream<int>(input), views::istream<int>(input)))
std::print("({}, {}), ", i, j);
std::println();
auto input2 = std::istringstream("a 1 b 2 c 3");
for (auto [i, j] : views::zip(views::istream<char>(input2), views::istream<int>(input2)))
std::print("({}, {}), ", i, j);
}
However, g++ produces unexpected results:
First loop outputs (2, 1), (3, 4), (5, 6)
Second loop outputs nothing
The istream_view bound to a stream sets failbit on invalid input (e.g., reading 'a' as int), halting subsequent operations.
While the evaluation order of arguments of a function call is unspecified, leading to non-portable behavior,
enforcing an order that is consistent between
tuple-transform and tuple-for-each does no hurt.
Microsoft STL already implements tuple-transform by std::tuple{...}instead of std::tuple(...).
Maybe an LWG issue is in needed to specify left-to-right evaluation order for iterator constructions (begin()/end()) and iterator advancements (operator++) in zip_view and related adaptors.
Received on 2025-06-16 23:55:49