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

I have a C++ program where I am trying to sort my maps by value, rather than by key.

From this question STL map--> sort by value?, 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 notice 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 complier already know from my type definition?

Answers


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;

Need Your Help

how to print a PDF on an unmapped network printer in java?

java networking printing

How to print a PDF on an unmapped network printer in java?

How to solve cross domain security error. in html 5 when using Canvas.getImageData

html5 canvas cross-domain getimagedata

I have a cross domain problem when using the image from amazon. I tried to use the Canvas.getImageData function but there is a security issue. It works on firefox when i set it to img.crossOrigin =