为什么标准容器迭代器不会重载"->*"?

Why standard container iterators don't overload `->*`?

本文关键字:gt 重载 标准 迭代器 为什么      更新时间:2023-10-16

显然,如果你重载->->*它不会自动工作,并且必须手动重载。

为什么标准容器的迭代器除了->之外,不会重载->*,强制使用(*iter).*mem_ptr而不是iter->*mem_ptr

#include <iostream>
#include <vector>
struct S
{
int x;
};
int main()
{
std::vector<S> vec = {{42}};
auto mem_ptr = &S::x;
std::cout << (*vec.begin()).*mem_ptr << 'n'; // This line compiles.
std::cout << vec.begin()->*mem_ptr << 'n'; // This line doesn't compile.
}

需要注意的是,这些问题通常无法回答,以下是operator->*()可能不会过载的几个原因。虽然有可能真正的答案是没有人想到它。如果这对您来说是一个重要的缺失语言功能,您可以随时提交提案。


对于初学者来说,ptr->*pmd通常不是一个非常常用的表达方式。因此,你不能写it->*pmd的事实并不是大多数人错过的,尤其是当(*it).*pmd以 2 个额外字符为代价实现完全相同的目标时。这里的潜在上行空间似乎相当小。尽管如此,迭代器应该与指针一致,所以这是有意义的。但。。。

指向成员的指针不仅仅是指向成员数据的指针,我们还可以具有指向成员函数的指针,并且可以编写(ptr->*pmf)(),其中ptr->*pmf本身的格式不正确。你根本无法用operator->*获得这些语义 - 要使调用操作正常工作,ptr->*pmf基本上必须返回一个 lambda。所以现在,这实际上变得相当复杂 - 除非你想只支持ptr->*pmd.使用任何方法,您都与指针不一致。

对于输入迭代器,您根本不希望支持operator->*(),因为它会产生一个立即悬而未决的引用。

就我个人而言,成本(弄清楚如何指定这些运算符,为哪些迭代器以及如何处理指向成员函数的指针)似乎并不值得(在很少编写的表达式中保存 2 个字符)。