0

I have a map that uses std::pair as key and int as value:

std::map<std::pair<int, int>, int> mymap;

I want to create a "view" on this map, so that I can use a different comparator with the goal of changing the iteration order without having to make a copy of the map. Based on the example provided here I thought the correct way to achieve my goal was to user std::reference_wrapper like so:

std::map<std::reference_wrapper< std::pair<int, int> >, std::reference_wrapper<int>, MyComp> mymap_view(mymap.begin(), mymap.end());

This does not compile with an (for me*) obscure error:

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1226:17: error: no matching member function for call to 'insert'
                insert(__e.__i_, *__f);
                ^~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/map:1011:13: note: in instantiation of function template specialization 'std::map<std::reference_wrapper<std::pair<int, int>>, std::reference_wrapper<int>, MyComp>::insert<std::__map_iterator<std::__tree_iterator<std::__value_type<std::pair<int, int>, int>, std::__tree_node<std::__value_type<std::pair<int, int>, int>, void *> *, long>>>' requested here
            insert(__f, __l);
            ^
main.cpp:66:98: note: in instantiation of function template specialization 'std::map<std::reference_wrapper<std::pair<int, int>>, std::reference_wrapper<int>, MyComp>::map<std::__map_iterator<std::__tree_iterator<std::__value_type<std::pair<int, int>, int>, std::__tree_node<std::__value_type<std::pair<int, int>, int>, void *> *, long>>>' requested here
    std::map<std::reference_wrapper< std::pair<int, int> >, std::reference_wrapper<int>, MyComp> mymap_view(mymap.begin(), mymap.end());
... a number of candidates considered and reasons why not viable ...

The use of MyComp seems of no influence: leaving it out results in the same error as far as I can tell.

What am I missing here?


*I'm trying to get back to C++ after many years of absence (according to my colleague, I'm so rusty that tetanus shots are required), so maybe I'm missing something obvious. There is a number of questions related to std::map, std::reference_wrapper, etc. and I think I have checked all of them, but without finding an answer.

Ludo
  • 813
  • 1
  • 9
  • 21
  • Can you show us the line where the compilation failed? – gerum Sep 06 '22 at 20:37
  • 1
    You cannot modify map order directly or indirectly, that will break `std::map` invariant. You can use Boost.MultiIndex instead. – Slava Sep 06 '22 at 20:42
  • 1
    I doesn't make sense to have a key which behaves like a reference. The key has to be a value. Otherwise, when the referenced value changes, the container gets into an invalid state with invalid ordering. What you are asking for doesn't make sense. – Jeffrey Sep 06 '22 at 20:42
  • 2
    the dupe explains how to use reference wrapper for the keys (they are `const`!), though you'll get a different error for reference wrapper mapped values https://godbolt.org/z/hMnjvo4sK. You can use pointers (or iterators?) – 463035818_is_not_an_ai Sep 06 '22 at 20:51
  • 1
    The trick here is that `key_type` is always const in a `map`, so you have to init a referece-map with references to constant keys – The Dreams Wind Sep 06 '22 at 20:57
  • Use a map (with the key ordering desired) to the map entries. (It'll be invalidated if the primary map is modified.) If it's a "throw away" temporary, use a vector of pointers and sort the vector as appropriate for your sort criteria. – Eljay Sep 06 '22 at 21:02
  • 1
    https://godbolt.org/z/PzGM7f37d for the reference – The Dreams Wind Sep 06 '22 at 21:57
  • Thanks @TheDreamsWind to comment/answer despite the question being closed. The linked duplicate focusses on the comparator, hence I had not seen the missing `const` was my problem. – Ludo Sep 07 '22 at 07:26

0 Answers0