gpt4 book ai didi

c++ - 转换 View 的 std::prev 上的未定义行为

转载 作者:行者123 更新时间:2023-12-04 04:30:14 25 4
gpt4 key购买 nike

考虑以下代码(click here for godbolt):

#include <algorithm>
#include <ranges>
#include <vector>

int main() {
auto v = std::vector<short>{1, 2};
auto view = v | std::views::transform([] (auto i) { return static_cast<int>(i); });
auto it = view.begin() + 1;
auto prev_it = std::ranges::prev(it); //this one is fine
//auto prev_it = std::prev(it); //this one dies with an infinite loop

return *prev_it;
}
主要问题:调用 std::prev而不是 std::ranges::prev在迭代器上使 gcc 陷入无限循环。这意味着存在编译器错误或代码调用 std::prev调用未定义的行为——它是哪一个?

关于后者的一些想法: std::prev 需要 LegacyBidirectionalIterator , 而 std::ranges::prev 需要 concept bidirectional_iterator .据我了解,这两者之间的唯一区别是(取自双向迭代器的描述):

Unlike the LegacyBidirectionalIterator requirements, the bidirectional_iterator concept does not require dereference to return an lvalue.


如果这确实意味着调用 std::prev调用未定义的行为:当使用新类型的迭代器调用时,基本上所有非范围算法都会调用未定义的行为,如 LegacyForwardIteratorforward_iterator共享相同的差异?旧算法的约束是否可以不放松到新的迭代器类型,以避免这种情况,因为这仍然是向后兼容的?

最佳答案

This means there’s a compiler bug or the code calling std::prev invokes undefined behaviour – which one is it?


后者,尽管 libstdc++ 应该能够检测到此故障并更好地诊断它 as it does if you ask it to .
这里的问题是:
auto view = v | std::views::transform([] (auto i) { return static_cast<int>(i); });
view的迭代器是 C++20 随机访问迭代器,但是因为它们的引用类型是纯右值 int ,它们只能是 C++17 输入迭代器。这正是 C++20 之前的迭代器模型的工作方式:前向迭代器需要一个真正的引用。 std::ranges::prev使用 C++20 迭代器类别, std::prev使用 C++17(或真正的 C++98)迭代器类别。和 std::prev需要 BidirectionalIterator .未指定库需要在多大程度上尝试验证迭代器确实是双向的,但是 prev(it, n)指定为 advance(it, -n); return it;advance(it, n)对于非双向迭代器只会循环直到它到达 n ... 负数 n显然永远不会发生。
也就是说,如果你使用 Ranges,你应该使用 std::ranges::meow而不是 std::meow在所有情况下,因为这个迭代器类别不同。这种情况非常引人注目,因为它是“有效”与“无限循环”,但请注意 std::next(it, 100)将是一个递增 it 的循环100 次,而 std::ranges::next(it, 100)将返回 it + 100 ,所以即使他们都“工作”,这仍然是一个显着的差异。

关于c++ - 转换 View 的 std::prev 上的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68486663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com