std::views::iota视图的迭代器属于什么迭代器类别?
std::views::iota视图的迭代器属于什么迭代器类别?
嘿,你发现的这个情况我之前也留意过,来给你唠唠到底是咋回事~
先把你的测试代码贴出来方便大家参考:
#include <ranges> int main() { auto view = std::views::iota(0ULL, 10000000000ULL); static_assert( std::is_same_v< std::iterator_traits<decltype(view.begin())>::iterator_category , std::input_iterator_tag> ); }
你在libc里得到这个断言成立的结果,是不是有点摸不着头脑?其实这是旧迭代器标签体系和C20新迭代器规则的“代沟”导致的:
按照C++20的标准,你这种指定了起始和结束值的有限iota视图,它的迭代器其实完全具备random_access_iterator的能力——加减整数偏移、随机访问元素、位置比较这些操作都能支持,妥妥的随机访问迭代器级别。
那为啥std::iterator_traits返回的是input_iterator_tag呢?这是libc的实现细节问题:C20之后的迭代器更依赖concept来定义能力,而旧的iterator_category标签在这个iota迭代器类型上没有被显式特化,导致std::iterator_traits只能默认 fallback 到input_iterator_tag,但这完全没体现出它的真实能力。
如果要正确判断这个迭代器的真实类别,别再用旧的标签体系了,直接用C++20的concept来检查,比如加个这样的断言:
static_assert(std::random_access_iterator<decltype(view.begin())>);
这个在libc++里肯定能通过,因为这个迭代器确实能完成随机访问的所有操作。
另外提一嘴,如果是无限的iota视图(比如只写std::views::iota(0ULL)没给结束值),那它的迭代器就只能算forward_iterator——毕竟没有终点,没法往回跳或者计算偏移,只能一直往前迭代。
备注:内容来源于stack exchange,提问作者Георгий Гуминов
相关产品推荐
相关产品推荐

