1

I have defined class that maintains a sorted map of doubles maps that to other data structures. Depending on the use case I want that other to be in ascending or descending order.

struct Book {
  std::map<double, Level> levels;

  // More complexity ...

  void process(Tick &t);

  const unsigned amount;

  // More stuf ...

  Book(const unsigned amount) :  levels(), id_price() {}

};

Ideally, this should be specified in the constructor for Book. I could for example pass std::less<double>() but that won't work because I can't use variables to declare the map levels, right? Would it work with templates? I don't want to make it type generic. It should be doubles to not add unnecessary complexity. Ideas?

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
Joachim
  • 3,210
  • 4
  • 28
  • 43

2 Answers2

3

You can define a custom comparator along these lines:

class comparator {

public:

      bool descending;

      comparator(bool descending) : descending(descending) {}

      bool operator()(double a, double b) const
      {
            return descending ? b < a:a < b;
      }
};

Then, in your class, define your map specifying this comparator class:

std::map<double, Level, comparator> levels;

Your constructor then needs to explicitly initialize this comparator, and use it to initialize your class's map. std::map's constructor takes an optional parameter, that passes an instance of the comparator class the map will use. Then, for each instance of your Book, its constructor can specify which way its levels will be sorted.

P.S. A double is a poor choice for a map key, but that would be a different question.

Community
  • 1
  • 1
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
2

You can define your map to use a custom comparator

struct Compare
{
    bool operator()(double l, double r) const {
        return cmp(l, r);
    }

    std::function<bool(double, double)> cmp;
};

Then you'd define your map as following:

std::map<double, Level, Compare> levels;

and the constructor

template<typename T>
Book(T comparator) :  levels(Compare{comparator}) {}

And then you can initialize your map with any comparator you would like

Book a(std::less<>{});

If you don't want the overhead of std::function you can implement more rigid logic right in your comparator.

krzaq
  • 16,240
  • 4
  • 46
  • 61
  • 1
    Shouldn't the comparator be on double? – Joachim Oct 01 '16 at 22:37
  • 1
    It should. Thanks! I guess the editbox doesn't make for a great IDE. – krzaq Oct 01 '16 at 22:38
  • @joachim: using `Book a(std::less<>());` in this example hits [most vexing parse](https://en.wikipedia.org/wiki/Most_vexing_parse). If you have more constructor arguments that cannot be misuonderstood the same way, then it's most likely fine. – krzaq Oct 01 '16 at 23:05