Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort C++ map keys with std::greater?

Tags:

c++

I'm creating a std::map<int, int> in C++ that I'd prefer to have they keys sorted from highest to lowest instead of the default sort order. My research lead me to std::greater which looked promising but when trying to use it I'm getting a compile error:

invalid type argument of unary ‘*’ (have ‘int’)

My map declaration is:

std::map<int, int, std::greater<int> > numMap;

And the error is getting thrown from this function:

void Row::addNumber(int num, int pos) {
    numMap.insert(num, pos);
}

Answers to similar questions such as this include parenthesis in the declaration, i.e. std::greater() - but when I include those I get multiple errors regarding a function returning a function.

like image 571
frostmatthew Avatar asked Feb 16 '13 20:02

frostmatthew


2 Answers

The problem – call of std::map::insert member function with invalid parameters: there are two integer values provided; but there must be std::pair<int, int>. Please see the reference: std::map::insert.

Preferable option

For convenience (just not to repeat the map type parameters), create a typedef for the map:

typedef std::map<int, int> IntMap;

The std::map has type definition for std::pair (pair representation) – std::map::value_type. So, for example, if there is a std::map<int, int> the std::map::value_type would be std::pair<int, int>.

Use the std::map::value_type constructor (IntMap::value_type in this case):

class Row {
public:
    void Row::addNumber(int num, int pos)
    {
        m_numMap.insert(IntMap::value_type(num, pos));
    }

private:
    typedef std::map<int, int> IntMap;
    IntMap m_numMap;
};

Alternatives:

  1. Use std::make_pair() function:

    #include <utility>
    
    ...
    
    void Row::addNumber(int num, int pos)
    {
        numMap.insert(std::make_pair(num, pos));
    }
    
  2. Directly use std::pair constructor:

    void Row::addNumber(int num, int pos)
    {
        numMap.insert(std::pair<int, int>(num, pos));
    }
    
like image 170
Sergey Vyacheslavovich Brunov Avatar answered Oct 28 '22 23:10

Sergey Vyacheslavovich Brunov


A bit more pedantic than Sergey's answer (which also definitely works), instead Use:

typedef std::map<int, int, std::greater<int> > MyMap;
MyMap numMap;

void Row::addNumber(int num, int pos)
{
    numMap.insert(MyMap::value_type(num, pos));
}

The benefit being that if you change the type of the map, you have less code to change later. And much less likely but still possible, if the implementation of std::map changes its value_type from std::pair to something else (in a future version of the stl), you are impervious to that change.

like image 43
eladidan Avatar answered Oct 28 '22 22:10

eladidan