【问题标题】:Why standard container iterators don't overload `->*`?为什么标准容器迭代器不会重载`->*`?
【发布时间】:2018-02-05 15:34:59
【问题描述】:

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

为什么除了->之外,标准容器的迭代器不会重载->*,从而强制使用(*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-&gt;,则在返回的值上再次调用operator-&gt;,递归,直到operator-&gt;到达返回一个普通指针。之后,将内置语义应用于该指针。" en.cppreference.com/w/cpp/language/operator_member_access 即存在显着差异。
  • 标准容器迭代器是否超载operator-&gt;? std:.vector 应该简单地使用 T* 作为迭代器。
  • 重载指向成员访问运算符的指针与其他重载不同,因为它的返回类型取决于参数的类型,因此必须是支持所有类型成员的模板。也许这是部分原因......
  • @manni66 是的,标准容器迭代器(都是输入迭代器)会重载operator-&gt;。除了 std::vector 之外,还有其他容器不能简单地使用指针。 std::vector::iterator 也不需要是指针。
  • @manni66 见std::vector&lt;bool&gt;(代理访问)虽然他们现在希望他们没有。

标签: c++ iterator operator-overloading language-lawyer


【解决方案1】:

请注意,这些问题通常无法回答,以下是operator-&gt;*() 可能不会超载的几个原因。尽管可能真正的答案是没有人想到它。如果这对您来说是一个重要的缺失语言功能,您可以随时submit a proposal


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

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

对于输入迭代器,您根本不想支持operator-&gt;*(),因为它会立即产生一个悬空引用。

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

【讨论】:

    猜你喜欢
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 2014-07-18
    • 2020-10-14
    相关资源
    最近更新 更多