为什么 C++ std 容器迭代器会忽略其底层容器的某些模板参数?

Why do C++ std container iterators ignore some template parameters of their underlying container?

提问人:Alexander Richter 提问时间:9/16/2022 更新时间:9/20/2022 访问量:99

问:

这是一个具体的例子。在下面的代码中,我本来会预料到编译错误,例如“无法将 std::map<int、int、cmp>::iterator 类型的值分配给 std::map<int、int>::iterator 类型的变量”。但是,我能够毫无问题地编译代码(g++ C++20 Wall)。谢谢你的帮助。

#include <map>

struct cmp {
    bool operator()(const int a, const int b) const { return a > b; }
};

int main(int argc, char *argv[]) {

    std::map<int, int> m1;
    std::map<int, int>::iterator m1_it = m1.begin();

    std::map<int, int, cmp> m2;
    std::map<int, int, cmp>::iterator m2_it = m2.begin();

    // Why do these work?
    m1_it = m2.begin();
    m2_it = m1.begin();

    return 0;
}

C++ 模板 迭代器 std

评论

3赞 NathanOliver 9/16/2022
迭代器并不关心树是如何构建的,它只是遍历它。
0赞 Peter 9/16/2022
为什么您认为更改比较器的类型会更改迭代器的类型?
0赞 molbdnilo 9/16/2022
换句话说:一旦树被构建,顺序就完全由树的结构决定。
1赞 Ben 9/16/2022
不过,这很有趣,也很微妙。他们可以轻松地在模板化容器类中定义积分器,在这种情况下,您将拥有两种不同的迭代器类型。我想知道该标准是否真的指定迭代器不关心 cmp。我有点惊讶;如果你问,我会认为你会知道仅根据迭代器类型进行什么排序。
1赞 Human-Compiler 9/16/2022
通常,该标准是关于迭代器如何实现的抽象。对于大多数容器,它只是命名它需要的迭代器类型(转发、随机访问等),而不是实现。最有可能的是,GCC 不关心模板参数,因为迭代器不需要它来遍历(树节点不使用比较,遍历只是在有序节点上)。不包括该参数还有一个额外的好处,即类型重复更少,从而减少了 rtti、调试符号等CompareCompare

答:

2赞 Jarod42 9/19/2022 #1

标准对迭代器类型设置了很少的约束,只是施加了一些行为。

特别:

  • 他们不必在.所以可能是 的有效迭代器。namespace stdT*std::vector<T>

  • 它们不必具有与容器相同的模板参数。对于上面的例子,可能是 for any 的迭代器。T*std::vector<T, Allocator>Allocator

然而,事实上,它的类型安全性较低,模板参数较少,允许的实例化较少(编译速度更快,生成的类似代码较少,...

请注意,您的代码可能无法针对使用所有模板参数作为迭代器的编译器/库进行编译。

1赞 MSalters 9/19/2022 #2

一个实际原因是这可能会导致可执行文件更小。两种映射类型可以共享一个迭代器类型,因此所有迭代器函数也会共享。