0

if I have a field in class like below,

class MyClass {
public:
    shared_ptr<map<int, int>> my_map;
}

The default map<int,int>'s comparison function is less<int>, but I would like to initialize my_map as

my_map = make_shared<map<int, int, greater<int>>>();

sometimes,

This doesnt compile, what other way I can have a shared_ptr<map<int, int>> that in two different object of MyClass, one has less<int> and the other have greater<int> so that the my_map in each object is sorted differently?

tesla1060
  • 2,621
  • 6
  • 31
  • 43

4 Answers4

2

You can use a custom comparator, something like:

struct my_comparator {

     bool the_other_way=false;

     my_comparator(bool flag) : the_other_way{flag} {}

     bool operator()(int a, int b) const
     {
         return the_other_way ? a > b: a < b;
     }
};

And construct a std::map<int, int, my_comparator>.

std::map has an overloaded constructor that takes an instance of the comparator object as a parameter. You can simply construct each individual map, accordingly.

typedef std::map<int, int, my_comparator> my_map;

my_map m1{my_comparator{false}};

my_map m2{my_comparator{true}};
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
2

what other way I can have a shared_ptr<map<int, int>> that in two different object of MyClass, one has less<int> and the other have greater<int> so that the my_map in each object is sorted differently?

You can specify std::function as the template argument for comparator as

std::shared_ptr<std::map<int, int, std::function<bool(int,int)>>> my_map;

and initialize it with std::less<int>

my_map = std::make_shared<std::map<int, int, std::function<bool(int,int)>>>(std::less<int>{});

or std::greater<int>.

my_map = std::make_shared<std::map<int, int, std::function<bool(int,int)>>>(std::greater<int>{});
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • It woukd be [expensive to do `std::function`](https://stackoverflow.com/questions/5057382/what-is-the-performance-overhead-of-stdfunction), where it fits with just `uing functionPointer = bool(*)(int)(int)`. – Const Aug 22 '20 at 19:20
  • @Const But `std::less` and `std::greater` can't be used with function pointer. – songyuanyao Aug 23 '20 at 01:15
  • thanks for this answer, i have tested, it works, just a further question, I believe you are refering to this constructor `explicit map (const key_compare& comp, const allocator_type& alloc = allocator_type());` here http://www.cplusplus.com/reference/map/map/map/ ? How did you know that the return type is `std::map>`? I cant find this anywhere in the official doc. – tesla1060 Aug 24 '20 at 01:43
  • @tesla1060 Yes, that constructor is used. The type, i.e. `std::map>` is specified as the template argument when calling `std::make_shared`, then we'll get a `shared_ptr` pointing to `std::map>`. – songyuanyao Aug 24 '20 at 01:47
1

If you want to customize the internal map with a different comparator for different objects, you can template the class to accept a comparison object, like this:

template<typename Compare = std::less<int>>
class MyClass 
{
  public:
    std::shared_ptr<std::map<int, int, Compare>> my_map;
};

and then create different objects:

int main()
{
    MyClass<> a;   // std::less<int> by default
    MyClass<std::greater<int>> b;
}

Here's a demo.

cigien
  • 57,834
  • 11
  • 73
  • 112
0

The comparator is part of the type declaration, so your member would need to include the comparator type:

class MyClass {
public:
    shared_ptr<map<int, int, greater<int>>> my_map;
}

Also, you are missing a '>' in the assignment. It should be:

my_map = make_shared<map<int, int, greater<int>>>();

See cigien's answer if you want to templatize your class to use different comparators (as the question implies).

Dave
  • 4,282
  • 2
  • 19
  • 24