Prashant Singh
Prashant Singh

Reputation: 23

Is there any uniform way of creating custom comparator in c++?

Basically I need a way to create comparator in a uniform manner for comparing in sort() function and priority queue. It will be easier to remember also.

My doubt is why the priority queue is using "Comp" and sort is using "Comp()". Is there any other way so that both can use the same format? Kindly tell some standard way. Thanks.

I am trying to compare the class in this question : https://practice.geeksforgeeks.org/problems/minimum-platforms/0 .

Code : https://ide.geeksforgeeks.org/R8snxdJl1B .

Link for below code.

// constructing priority queues
#include <iostream>       // std::cout
#include <queue>          // std::priority_queue
#include <vector>         // std::vector
#include <functional>     // std::greater
#include <algorithm>
using namespace std;

class Comp{
public:
  bool operator() (const int& lhs, const int&rhs) const{
    return (lhs>rhs);
  }
};

int main (){
  int myints[]= {10,60,50,20};

  // using mycomparison:
  priority_queue<int, vector<int>, Comp> pq;
  cout << "pq is using mycomparison" << endl;

  vector<int> v= {10,60,50,20};
  sort(v.begin(), v.end(), Comp());
  cout << "sort using mycomparison()" << endl;
  return 0;
}

Upvotes: 2

Views: 246

Answers (2)

Eric
Eric

Reputation: 97571

why the priority queue is using "Comp" and sort is using "Comp()"

priority_queue is a type, sort is a function. Functions can infer template arguments, but default-constructed types have no arguments to infer types from.

If you call the constructor, the template deduction guides from C++17 will let you use the Comp() form:

std::priority_queue pq{Comp(), std::vector<int>()};

If you only have C++11 or 14, you can write a helper function to build one with a custom comparator:

template<typename T, typename Container = std::vector<T>, typename Comp>
std::priority_queue<T, Container, Comp> make_priority_queue(Comp comp) {
    return std::priority_queue<T, Container, Comp>{comp};
}

used as

auto pq = make_priority_queue<int>(Comp());

Upvotes: 4

sweenish
sweenish

Reputation: 5202

Instead of a homespun functor, use a lambda instead. They're much simpler, and they work for both. Any further differences in syntax are just how std::sort and std::priority_queue were designed. But, you never have to remember Comp() vs. Comp.

#include <algorithm> // std::sort
#include <array>
#include <iostream>  // std::cout
#include <queue>     // std::priority_queue
#include <vector>    // std::vector

int main() {
  // Lambda instead of functor
  constexpr auto Comp = [](auto& lhs, auto& rhs) { return lhs > rhs; };

  // std::array as an iterable type for priority_queue
  std::array<int, 4> myints = {10, 60, 50, 20};

  // using mycomparison:
  // As someone else stated, you can leave all this template stuff out in C++17
  // std::priority_queue pq(Comp, myints);
  std::priority_queue<int, decltype(myints), decltype(Comp)> pq(Comp, myints);
  std::cout << "pq is using mycomparison" << std::endl;

  std::vector<int> v = {10, 60, 50, 20};
  std::sort(v.begin(), v.end(), Comp);
  std::cout << "sort using mycomparison()" << std::endl;

  return 0;
}

I also removed the using namespace std; line as that's a bad practice. If you don't like all the std:: stuff, you can use using statements instead.

using std::cout;
using std::vector;
// etc.

Link

Upvotes: 2

Related Questions