自定义迭代器无法创建std::ranges::subrange的问题求助
解决自定义迭代器与哨兵配合的
std::ranges::subrange编译问题 一、修复第一个MakeNeighborRange的编译问题
你的第一个实现无法编译,核心原因是NeighborIteratorSentinel与NeighborIterator未满足std::sentinel_for的双向比较约束,同时迭代器的operator*/operator->返回值不符合输入迭代器的标准要求。以下是修复后的完整代码:
#include <ranges> struct CellCoord { size_t col; size_t row; }; struct NeighborIteratorSentinel {}; class NeighborIterator { public: NeighborIterator(size_t link_id) : linkId(link_id) {} // 满足std::semiregular所需的默认构造要求 NeighborIterator() : NeighborIterator(0) {} using iterator_category = std::forward_iterator_tag; using value_type = CellCoord; using difference_type = std::ptrdiff_t; using pointer = const CellCoord*; using reference = const CellCoord&; // 修正operator*返回引用类型,符合输入迭代器规范 const CellCoord& operator* () const { static CellCoord current; current = cur(); return current; } // 修正operator->返回指针类型 const CellCoord* operator-> () const { static CellCoord current; current = cur(); return ¤t; } NeighborIterator& operator++ () { ++linkId; return *this; } NeighborIterator operator++ (int) { NeighborIterator tmp = *this; ++linkId; return tmp; } // 默认拷贝、移动、赋值语义保留 NeighborIterator(const NeighborIterator&) = default; NeighborIterator(NeighborIterator&&) = default; NeighborIterator& operator=(const NeighborIterator&) = default; NeighborIterator& operator=(NeighborIterator&&) = default; // 迭代器与哨兵的相等/不等比较 bool operator == (const NeighborIteratorSentinel&) const noexcept { return linkId == linkCount; } bool operator != (const NeighborIteratorSentinel&) const noexcept { return !(*this == NeighborIteratorSentinel{}); } protected: CellCoord cur() const { return {linkId, linkId}; } private: size_t linkId; static constexpr size_t linkCount = 5; }; // 补充哨兵与迭代器的双向比较运算符 bool operator == (const NeighborIteratorSentinel&, const NeighborIterator& iter) noexcept { return iter == NeighborIteratorSentinel{}; } bool operator != (const NeighborIteratorSentinel& s, const NeighborIterator& iter) noexcept { return !(s == iter); } inline auto MakeNeighborRange() { return std::ranges::subrange(NeighborIterator(0u), NeighborIteratorSentinel{}); }
关键修复点:
- 双向对称比较:为
NeighborIteratorSentinel添加与NeighborIterator的==/!=运算符,满足std::sentinel_for要求的双向相等比较约束。 - 迭代器返回值合规:修改
operator*和operator->返回const CellCoord&和const CellCoord*,符合C++标准中输入迭代器对operator*必须返回引用类型的要求。 - 默认构造函数:添加默认构造函数,满足
std::semiregular概念的要求,避免std::ranges::subrange的额外约束报错。
二、std::sentinel_for的具体约束
根据C++20标准,std::sentinel_for<S, I>概念需满足以下核心条件:
std::input_or_output_iterator<I>:迭代器I必须是输入或输出迭代器。- 双向相等比较:
I与S之间必须支持双向的相等判断,即i == s和s == i都能合法调用且结果一致。 - 等价关系(针对前向迭代器):如果
I是前向迭代器,I与S的相等比较必须是等价关系(自反、对称、传递),且迭代器的相等性不会影响与哨兵的比较结果。 - 终止语义:若迭代器
i等于哨兵s,则递增i后i仍等于s(哨兵代表终止位置,不会被迭代器越过)。
内容的提问来源于stack exchange,提问作者Alexey Starinsky
相关产品推荐
相关产品推荐

