1

This code fails to compile:

void foo(vector<unique_ptr<pair<int, int>>> bar)
{
    bar.begin()->first;
}

What's the problem here? Shouldn't operator-> drill down until pair?

  • 2
    "_Shouldn't `operator->` drill down until `pair`?_" No. Why should it? It returns the underlying element, which is `unique_ptr>`. – Algirdas Preidžius Feb 24 '20 at 17:24
  • 1
    Which has its own `operator->`, so normally C++ calls that (usually called `operator->`'s drill down behavior. – Artikash-Reinstate Monica Feb 24 '20 at 17:28
  • 3
    Just because a class has a `operator->` doesn't mean that it should be called automatically. How would the compiler know when to call it vs. when to not? How would the compiler know you want the `pair` inside it, and not the `unique_ptr`? – ChrisMM Feb 24 '20 at 17:31
  • Have you tried bar[0]->first ? – Hazem Abaza Feb 24 '20 at 17:37
  • @HazemAbaza Of course I know I *could* just dereference the iterator and proceed, but it was surprising since I thought `operator->` kept going until it hit a class which doesn't have one. – Artikash-Reinstate Monica Feb 24 '20 at 17:39
  • @Artikash "_I thought `operator->` kept going until it hit a class which doesn't have one._" What gave you such an idea? Where did you read that it worked this way? As already stated in the comments: what if you didn't recurse to the bottom? How would you avoid such recursing, if this was the behavior? – Algirdas Preidžius Feb 24 '20 at 17:54
  • @AlgirdasPreidžius Because I have written a class which relied on that behavior: https://github.com/Artikash/Textractor/blob/master/include/common.h#L62 I thought you had to call `.operator->().operator->()...` manually if you wanted to control it. – Artikash-Reinstate Monica Feb 24 '20 at 17:57
  • @Artikash "_I have written a class which relied on that behavior_" is a recursive argument. I asked, where, in which documentation, C++ standard, etc., have you read that this is the expected behavior? Hence, what gave you this idea? Note: calls `x->y`, and `x.operator->()->y` are equivalent. The first is merely syntactic sugar for the second. – Algirdas Preidžius Feb 25 '20 at 11:15
  • @AlgirdasPreidžius I don't remember what I was thinking when I wrote that class a year ago lol. What I do know is when I use that class now it does seem to behave like that: `Synchronized>(0,0)->first` does compile "since it successfully drills down until `pair` which doesn't have `operator->` so it stops then". That's what I thought, not realizing it actually stops at the second level because that level returns a raw pointer. – Artikash-Reinstate Monica Feb 25 '20 at 12:10

1 Answers1

2

Shouldn't operator-> drill down until pair?

The recursion of operator -> only works until you get a pointer type. Once that happens the recursion stops and you access what that pointer points to. In this case std::vector::iterator::operator-> returns a unique_ptr<pair<int, int>>* as that pointer type of the element in the vector. Once you hit that pointer, you are left accessing the members of the unique_ptr, not the pair<int, int> it points to.

You can get what you want using

(*bar.begin())->first;

so now you are using operator-> of unique_ptr<pair<int, int>>.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402