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

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

Apparently ->* doesn't work automagically if you overload ->, and has to be overloaded manually.

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

Why iterators for standard containers don't overload ->* in addition to ->, forcing usage of (*iter).*mem_ptr instead of 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 << '
'; // This line compiles.

    std::cout << vec.begin()->*mem_ptr << '
'; // This line doesn't compile.
}

推荐答案

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

With the caveat that these questions aren't typically answerable, here are a few reasons why operator->*() may not be overloaded. Although it's possible the real answer is that nobody thought of it. And if this, to you, is an important missing language feature, you could always submit a proposal.

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

For starters, ptr->*pmd just isn't a very commonly used expression in general. So the fact that you cannot write it->*pmd isn't something that most people miss, especially when (*it).*pmd accomplishes exactly the same goal at the cost of just 2 extra characters. The potential upside here seems fairly small. Still, iterators should be consistent with pointers, so it would make sense. But...

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

Pointers to members aren't just pointers to member data, we can also have pointers to member functions and can write (ptr->*pmf)() today, where ptr->*pmf by itself is ill-formed. You can't get those semantics at all with operator->* - to get the call operation to work, ptr->*pmf would have to basically return a lambda. So now, this actually becomes fairly complicated - unless you want to just support ptr->*pmd. With any approach, you're inconsistent with pointers.

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

For input iterators, you don't want to support operator->*() at all since it would yield an immediately dangling reference.

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

To me, personally, the cost (figuring out how to specify these operators, for which iterators, and what to do about pointers to member functions) doesn't really seem worth the benefit (saving 2 characters in an expression that's rarely written).

相关文章