Home > Net >  Using std::swap_ranges with std::map
Using std::swap_ranges with std::map

Time:10-20

I would like to swap parts of two maps using a standard algorithm, but somehow iterators on map do not seem to be swappable. I am surely missing something.

Example

#include<map>
#include<algorithm>

auto function(std::map<int,int> m1, std::map<int,int> m2)
{
    auto first = m1.begin();
    auto last = first;
    std::advance(last, 3);
    std::swap_ranges(first, last, m2.begin());
}

Error

See it on compiler explorer: https://godbolt.org/z/6bn1xYTTr

In file included from /opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_tree.h:63,
                 from /opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/map:60,
                 from <source>:1:
/opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_algobase.h: In instantiation of 'void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = _Rb_tree_iterator<pair<const int, int> >; _ForwardIterator2 = _Rb_tree_iterator<pair<const int, int> >]':
/opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_algobase.h:212:16:   required from '_ForwardIterator2 std::swap_ranges(_ForwardIterator1, _ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = _Rb_tree_iterator<pair<const int, int> >; _ForwardIterator2 = _Rb_tree_iterator<pair<const int, int> >]'
<source>:9:21:   required from here
/opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_algobase.h:182:11: error: use of deleted function 'typename std::enable_if<(! std::__and_<std::__is_swappable<_T1>, std::__is_swappable<_T2> >::value)>::type std::swap(pair<_T1, _T2>&, pair<_T1, _T2>&) [with _T1 = const int; _T2 = int; typename enable_if<(! __and_<__is_swappable<_T1>, __is_swappable<_T2> >::value)>::type = void]'
  182 |       swap(*__a, *__b);
      |       ~~~~^~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_algobase.h:64:
/opt/compiler-explorer/gcc-12.2.0/include/c  /12.2.0/bits/stl_pair.h:715:5: note: declared here
  715 |     swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
      |     ^~~~
Compiler returned: 1

CodePudding user response:

std::map is implemented as some sort of binary search tree, and its structure depends on each item's key never changing. Thus the type returned by *m1.begin() is std::pair<const int, int>&. Note that the first int is const. You cannot modify it.

std::swap_ranges tries to swap each element of the first range with its corresponding element in the second range, but std::pair<const int, int>s can't be swapped due to the constness of their first element.

  • Related