How does C++ priority_queue customize the comparison function? What is the difference between the custom comparison function in sort?

1. How to customize the comparison function in C++ priority_queue and the difference from the custom comparison function in sort

First look at the template definition of priority_queue in the official C++ document:

template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

Notice:

  1. You don’t need to write the last two parameters, because there are default values, but if you write them, you must write both of them, and fill them in order !
  2. Compare is the class name! Not an object name !
    There are also many functions in the algorithm that use custom comparison functions, such as sort:
template <class RandomAccessIterator, class Compare>  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

What needs to be passed in here is not just the class name, but the object name!
You can pay attention to other internal ordered data structures in C++, such as map and set. You can see that these Compares are class names, not class objects! This is a very easy mistake to make.
map:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T>>
> class map;

set:

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

Summary: The most important thing is that the comparison function in sort must be an object, and priority_queue, etc. are class names !

2. The comparison functions are as follows:

Note: It is best to add a const qualifier after the function for the structure, otherwise an error may be reported when constructing objects such as priority_queue!
If possible the following error occurs:

Visual Studio Compiler Error C3848 An expression with type 'type' would lose some const-volatile
qualifiers to call 'function'

The solution is to add a const qualifier when overloading the function call operator, like the code in the first type below.

vector<pair<int, int>> vec;

The first one: using function objects. For what is a function object, please refer to What is a C++ function object (Function Object)?

结构体
struct compare {
    
    
	bool operator () (const pair<int, int>& A. const pair<int, int>& B) const {
    
    
		return A.second < B.second;
    }
}
sort(vec.begin(), vec.end(), compare{
    
    });
sort(vec.begin(), vec.end(), compare());

The second type: use a global function, which should be converted here. cmp is a function pointer, and a function object is actually used.
Since what is called here is an actual function object, it can be passed in directly (no additional constructor object) .


函数
bool cmp(const pair<int, int>& A. const pair<int, int>& B) {
    
    
	return A.second < B.second;
}
sort(vec.begin(), vec.end(), cmp);
// 不用加()

The third method: use the less or greater that comes with the standard library. Note that this method must also pass in a specific object. The following two methods can be used

less或者greater
sort(vec.begin(), vec.end(), less<pair<int, int>>()); 
sort(vec.begin(), vec.end(), less<pair<int, int>>{
    
    }); 

It can also be seen in the official document that in fact, less overloads the operator ()

std::less::operator()
bool operator()( const T& lhs, const T& rhs ) const;

So I think, less<pair<int, int>>{} is to construct an object of a class, and less<pair<int, int>>() should call less<pair<int, int directly >>The overloaded () method , but the former also calls the overloaded () method.
You can verify the structure (that is, the first method)
as follows:

结构体
struct compare {
    
    
	bool operator () (const pair<int, int>& A. const pair<int, int>& B) const {
    
    
		cout <<  "()" << endl;
		return A.second < B.second;
    }
}
sort(vec.begin(), vec.end(), compare{
    
    });
sort(vec.begin(), vec.end(), compare());

It can be found that both methods will output (), indicating that the overloaded () function is called during the comparison process.

References:

cppreference

Guess you like

Origin blog.csdn.net/Sansipi/article/details/127858218