Why do I need to repeat the sorting subroutine when declaring a std::set?

c++, c++11, dictionary, set, stl

Solution

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter;

You never specified what comparator the `set` should actually use. Change the above line to

set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter(compareCounts);

Without the comparator being specified, the `set` default constructs one (`nullptr`) and when it tries to use the comparator for inserting the second element, your code crashes.

You should just use a functor instead of a function pointer

struct compareCounts
{
    bool operator()(const pair<string, size_t> &lhs, 
                    const pair<string, size_t> &rhs) const
    {
        return lhs.second > rhs.second;
    }
};

set <pair<string, size_t>, compareCounts> sorted_counter;

Problem

In my C++ program I am trying to sort my maps by value, rather than by key. From this question, it seems clear that the way to do this is to create a set whose elements are pairs and which are sorted by my own less-than function. Here is some sample code where I try to do this: ``` #include <map> #include <set> #include <iostream> #include <string> using namespace std; bool compareCounts(const pair<string, size_t> &lhs, const pair<string, size_t> &rhs); int main (int argc, char *argv[]) { map <string, size_t> counter = { {"A", 1}, {"B", 2}, {"C", 3} }; set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter; for (map<string, size_t>::iterator it = counter.begin(); it != counter.end(); ++it) { cout << "About to add: " << it->first << ":" << it->second << endl; auto ret = sorted_counter.insert(*it); if (! ret.second) { cout << "ERROR adding this element!" << endl; } else { cout << "Element added ok" << endl; } cout << "Set is of size: " << sorted_counter.size() << endl; } return 0; } bool compareCounts(const pair<string, size_t> &lhs, const pair<string, size_t> &rhs) { return lhs.second > rhs.second; } ``` Here is the output: About to add: A:1 Element added ok Set is of size: 1 About to add: B:2 Segmentation fault: 11 I noticed that things come crashing down when I go to add the second element. I found that this is happening because it is now necessary to call my sorting subroutine, `compareCounts`. The fix was to change this line: ``` set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter; ``` to this: ``` set <pair<string, size_t>, decltype(compareCounts) *> sorted_counter(compareCounts); ``` Why do I need to specify the sorting subroutine `compareCounts` twice? Doesn't the compiler already know it from my type definition?

Original source

Related problems