0

In the below c++ calling reset() inside list, vector, map there is neither error nor warning.

however when I try to do it in set I get error.

error message is [ No matching member function for call to 'reset' ]

why this happened??? Can someone share your knowledge with the community??

std::shared_ptr<int> sp;
sp.reset(new int(11));
sp.reset();

std::map<int, std::shared_ptr<int>> my_map;
for (auto it = my_map.begin(); it != my_map.end(); ++it) {
  it->second.reset();
  (*it).second.reset();
}

std::list<std::shared_ptr<int>> my_list;
for (auto& x : my_list) {
  x.reset();
}

std::vector<std::shared_ptr<int>> my_vec;
for (auto it = my_vec.begin(); it != my_vec.end(); ++it) {
it->reset();
  (*it).reset();
}

std::set<std::shared_ptr<int>> my_set;
for (auto& x : my_set) {
  x.reset();      // ERROR!!!
}

for (auto it = my_set.begin(); it != my_set.end(); ++it) {
  it->reset();    // ERROR!!!
  (*it).reset();  // ERROR!!!
}
  • OS : Ubuntu18.04
  • Compiler: g++ 7.5.0-3ubuntu1~18.04
Kiseong Yoo
  • 97
  • 1
  • 7
  • 3
    Please don't add line-numbers to the [mcve] you show, it makes it very hard for us to copy it to try ourselves. If you want to point out some specific lines then add comments on those lines and mention them in the main question body. – Some programmer dude Jun 06 '20 at 08:20
  • 1
    The keys of a `std::set<>` are `const` and this is for good reasons. If they are changed this might violate their order but a well-defined order is essential for `std::set` (used for look-up). Hence, I'm sure that the `auto&` in `for (auto& x : my_set)` results in a `const` reference, and there is no `reset() const` in `std::shared_ptr` obviously. – Scheff's Cat Jun 06 '20 at 08:24
  • 1
    Modifying the keys might destroy the property of being a set; that every value only occurs once. (It might also destroy the ordering, but I consider that a smaller problem.) – molbdnilo Jun 06 '20 at 08:48
  • @Someprogrammerdude I editted removing the line nubmers, thanks – Kiseong Yoo Jun 06 '20 at 08:53

1 Answers1

5

The main problem is that std::set is an ordered container, and that ordering is done on insertion only.

To keep the order all keys in the set are constant and can't be modified.

You will have the same problem trying to modify the key of your std::map.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    The general solution to this problem in practice (take the value out, then optionally put it back) might improve this answer. Of course the OP has to then care about iterator invalidation. – Yakk - Adam Nevraumont Jun 06 '20 at 08:54
  • I kind of understand this answer and not. I think I've been using std::set<> without really understanding it. – Kiseong Yoo Jun 06 '20 at 08:54
  • But still I don't get that modifying the data 'inside' an object can affect how the container is ordered. Though I change the pointed object which is managed by the shared_ptr, it's still the same shared_ptr, isn't it? – Kiseong Yoo Jun 06 '20 at 09:04
  • 1
    @KiseongYoo Lets say you have a set of integers (.e.g `std::set`) with two keys, `1` and `2`. When you iterate over the set, they will come in the order `1` and `2`. Now lets say you want to modify the key `1` to become `3`? Since ordering is only done when adding keys to the set and not dynamically, that would mean that suddenly `3` would become "smaller" than `2` (come before `2` when iterating). Then the set would no longer be ordered. Because of this, you are not allowed to modify the keys in the set. – Some programmer dude Jun 06 '20 at 09:44
  • Now I see. In std::set the value itself is deeply related to own key, so we cannot modify the value. Thanks a lot – Kiseong Yoo Jun 06 '20 at 13:21
  • Today i was told that iterator of ordered stl, such as set, priority queue, heap is always const_iterator. Is this true? – Kiseong Yoo Jun 06 '20 at 13:26