0

I have this code:

#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <cctype>
#include <string>
...
void f() {
    std::set<std::pair<int, std::string>> orderByRating;
    /*...*/
    auto revIter = orderByRating.rbegin();
    int subsetSz = 2;
    auto cmp = [](std::pair<int, std::string> const & a, std::pair<int, std::string> const & b) {
        return a.second < b.second;
    };
    std::sort(revIter, std::next(revIter, subsetSz), cmp);
}

And I get this error

1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\algorithm(3212): error C2679: binary '-': no operator found which takes a right-hand operand of type 'const std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>' (or there is no acceptable conversion)
1>        with
1>        [
1>            _Ty=std::pair<int,std::string>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\xutility(1383): note: could be 'std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>> std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>::operator -(int) const'
1>        with
1>        [
1>            _Ty=std::pair<int,std::string>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\algorithm(3212): note: while trying to match the argument list '(const std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>, const std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>)'
1>        with
1>        [
1>            _Ty=std::pair<int,std::string>
1>        ]
1>c:\users\user\source\repos\consoleapplication1\consoleapplication1.cpp(66): note: see reference to function template instantiation 'void std::sort<std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<_Ty>>>>,topCompetitors::<lambda_885448e6a7e9e4442c4f55247636e75d>>(_RanIt,_RanIt,_Pr)' being compiled
1>        with
1>        [
1>            _Ty=std::pair<int,std::string>,
1>            _RanIt=std::reverse_iterator<std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<int,std::string>>>>>,
1>            _Pr=topCompetitors::<lambda_885448e6a7e9e4442c4f55247636e75d>
1>        ]
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\algorithm(3212): error C2672: '_Sort_unchecked': no matching overloaded function found
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\algorithm(3212): error C2780: 'void std::_Sort_unchecked(_RanIt,_RanIt,_Diff,_Pr)': expects 4 arguments - 3 provided
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\algorithm(3173): note: see declaration of 'std::_Sort_unchecked'

Can you help me to understand what's wrong and how to fix it? I want to sort by value subset from set

It means that I can sort only on random_iterator?

Or in that case are there any std methods to extract subset values to make vector out of them?

user3360601
  • 327
  • 3
  • 17
  • 1
    `std::set` is already sorted. Why do use `std::set` in the first place and not, for example, `std::vector`? – Evg May 10 '20 at 19:44
  • @Evg, but my set has key - int and value - string, and it it sorted by keys, not by values. I want to do sort for strings - values – user3360601 May 11 '20 at 08:51
  • 1
    Then you can change `std::pair` to `std::pair`. `std::set` is sorted by design to support fast set operations like [`std::set_intersection`](https://en.cppreference.com/w/cpp/algorithm/set_intersection), [`std::set_difference`](https://en.cppreference.com/w/cpp/algorithm/set_difference), etc. If you don't need to keep keys always sorted, most probably you don't need `std::set` at all. – Evg May 11 '20 at 09:28
  • @Evg, I'm sorry for offtopic, but what if I need to sort all strings by some numbers according to that strings, and sort strings with the same numbers alphabetically ? I tried to use set to do auto-sort by numbers, and I tried to do manual sort of some subsets of strings from that set – user3360601 May 11 '20 at 14:08
  • 1
    If you need the keep keys always sorted, `std::set` may be a good choice. If you need to resort some parts of `set`, you have to copy that part into another container, with `std::set` you can't do it in-place. – Evg May 11 '20 at 14:13

1 Answers1

2

You don't sort std::set.

It "sorts" itself, by the values of its elements.

That is a fundamental property of std::set.

You can override the criteria by which it is sorted, by providing a replacement Compare (or specialising the default, std::less) (ref).

Or, you can use a different container.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35