Skip to content

容器迭代器的设计问题及建议 #1

Description

@frederick-vs-ja

ADL 防御

考虑以下的 EvilPointer 类型:

struct Incomplete;
template<class T>
struct Holder {
    T t;
};

using EvilPointer = Holder<Incomplete>*;

倘若我等试图将某个迭代器实现为类模板特化 SomeIterator<EvilPointer>,则 i == i 会产生 ADL (实参依赖查找),进而要求关联类 Incomplete 完整,产生硬错误。换言之这样的实现不能满足迭代器的要求。

解决方案是将迭代器实现为类模板的非模板成员类,这可以避免用户提供的类型成为迭代器类型的关联类。

template<class T>
struct SomeContainerIteratorProvider {
    struct Iter {
        /* 具体实现 */
    };
};

template<class T>
using SomeContainerIterator = typename SomeContainerIteratorProvider<T>::Iter; // C++20 起此处不需要 typename

参考资料

最小化依赖的迭代器类型

通常来说容器迭代器应该只依赖元素类型,以及分配器所确定的指针类型(可能为缀饰指针)。

分配器、比较器、哈希器最好不影响迭代器的类型。

对于 std::array 以及定长的 std::span,编译时确定的长度最好不影响迭代器类型。但 std::array<T, 0> 的情况可能稍微特殊一点。

参考资料

比较运算符实现为隐藏友元

可以避免对其他类型查找运算符时该类的运算符参被纳入考虑,并且减少隐式转换的干扰。

const_iteratoriterator 的关系

隐式转换转换不应用继承实现,因为非 const 迭代器和 const 迭代器并没有 IS-A 关系。继承会允许经由基类子对象的赋值一个非 const 的迭代器指向本应只能由 const 迭代器访问的元素。

通过转换函数 operator T() 实现隐式转换可能会相对容易控制。

参考资料

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions