Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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 << '\n'; // This line compiles.

    std::cout << vec.begin()->*mem_ptr << '\n'; // This line doesn't compile.
}
like image 381
HolyBlackCat Avatar asked Feb 05 '18 15:02

HolyBlackCat


People also ask

Does std :: move invalidate iterators?

std::move does nothing on its own. The move assignment definitely invalidates iterators on both sides, though.

Why use iterators instead of pointers?

A pointer of type T* can point to any type T object. An iterator is more restricted, e.g., a vector::iterator can only refer to doubles that are inside a vector container.

What is a container What is an iterator?

An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualized as something similar to a pointer pointing to some location and we can access the content at that particular location using them.

What are the STL iterators and what is their purpose?

An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.


1 Answers

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.


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...

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.

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

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).

like image 53
Barry Avatar answered Sep 28 '22 01:09

Barry