I have encountered this greater<pair<int,int>> in many codes.
For example, in the initialisation of the priority queue [code below]
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
I tried a lot of googling but still couldn't find the best answer.
This is the std::greater type.
This is a function object type that does comparisons using the > operator. A rough implementation looks like this:
template<typename T>
struct greater {
constexpr auto operator()(T const& a, T const& b) const -> bool {
return a > b; // greater operator
}
};
In your example, this is being used to order the std::pairs in the priority_queue from "smallest" to "largest" using std::pair's operator >.
The std::greater is a template function object defined as:
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a > b; // greater operator
}
};
Now, the '>' operator is defined for std::pair as -
template <class T1, class T2>
bool operator> (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) { return rhs<lhs; }
Now, the '<' operator is defined as-
template <class T1, class T2>
bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{ return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); }
So, effectively, the function greater<pair<int, int>> works as-
template<typename T> struct greater {
constexpr bool operator()(T const& a, T const& b) const {
return a.first>b.first || ( (a.first<b.first) && (a.second>b.second));
}
};
That is, greater<pair<int, int>>(a, b) returns true if and only if the 'first' parameter of a is greater than b or if 'first' parameters are equal then 'second' parameter of a is greater than b.
This is a strict weak ordering.
Related
In a template function a std::vector shall get sorted. T can be a simple type or a std::pair e.g.,
std::vector<double> or
std::vector<std::pair<int,Something> >
When T is a pair then only the first element shall be compared. How can I implement the comparator for the two cases?
I have tried:
template<typename T>
inline bool smaller(const T& a,const T& b)
{
return a<b;
}
template<typename T,typename S>
inline bool smaller(
const std::pair<T,S>& a,
const std::pair<T,S>& b
)
{
return a.first<b.first;
}
template<typename T> inline void function(std::vector<T >& vVec)
{
...bla...
sort(vVec.begin(),vVec.end(),smaller<T>);
...bla...
}
but it does not work this way. I have also tried specialization but I do not find the right syntax to specialize the smaller() function.
You could just wrap it in a lambda:
std::sort(vVec.begin(),vVec.end(), [](const auto& a, const auto& b) { return smaller(a, b); });
One easy work around is to make both of your smaller functions opeator()'s of a smaller struct. Using
struct smaller
{
template<typename T>
bool operator()(const T& a,const T& b)
{
return a < b;
}
template<typename T, typename S>
bool operator() (const std::pair<T, S>& a, const std::pair<T, S>& b)
{
return a.first < b.first;
}
};
allows you to just pass a smaller to sort like
template<typename T> inline void function(std::vector<T >& vVec)
{
sort(vVec.begin(),vVec.end(),smaller{});
}
and in sort overload resolution will kick in on the two operator() smaller has and for any std::vector<std::pair>, the std::pair overload will be called.
I want to create a shared_ptr content-comparison functor to stand in for std::less<T> in associative containers and std algorithms. I've seen several examples of custom comparators that use the following (or similar) model:
template <typename T>
struct SharedPtrContentsLess {
bool operator()(const boost::shared_ptr<T>& lhs,
const boost::shared_ptr<T> rhs) const {
return std::less<T>(*lhs, *rhs);
//or: return (*lhs) < (*rhs);
}
//defining these here instead of using std::binary_functor (C++11 deprecated)
typedef boost::shared_ptr<T> first_argument_type;
typedef boost::shared_ptr<T> second_argument_type;
typedef bool return_type;
};
But why wouldn't I want to instead extend std::less? Like so:
template <typename T>
struct SharedPtrContentsLess : public std::less< boost:shared_ptr<T> > {
bool operator()(const boost::shared_ptr<T>& lhs,
const boost::shared_ptr<T> rhs) const {
return std::less<T>(*lhs, *rhs);
}
};
Does this buy me anything at all?
I would think this gets me the typedefs for free, as though I was extending the deprecated std::binary_function. In C++03, I actually would be extending it through std::less. However, this would also be portable from C++03 to C++11/14 and even C++17 when std::binary_function will be removed, as it just follows the changes in std::less.
I've read a bunch of answers on StackOverflow regarding std::less use, custom comparison functors, and even some of the Standard specs and proposals. I see specializations of std::less and guidance not to extend STL containers, but I can't seem to find any examples of extending std::less or guidance against it. Am I missing an obvious reason not to do this?
EDIT: Removed C++11 tag, as it is causing confusion to the answerers. I am hoping to get forward-portability, but C++03 is required. If you provide a C++11-only answer for others to use (totally fine), please note that.
You can create a reusable template towards any dereferencable object (i.e. any (smart) pointer) by simply forwarding the call to std::less or any other comparable object.
// c++11
template<template<class> Op, class T> struct deref_mixin;
template<template<class> Op, class T>
struct deref_mixin {
auto operator()(const T &l, const T &r) const
-> decltype(std::declval<Op<T>>()(*l, *r)) {
return Op<T>{}(*l, *r);
}
};
template<template<class> Op>
struct deref_mixin<Op, void> {
template<class T, class U>
auto operator()(const T &l, const U &r) const
-> decltype(std::declval<Op<T>>()(*l, *r)) {
return Op<void>{}(*l, *r);
}
};
template<class T> using less_deref = deref_mixin<std::less, T>;
template<class T> using greater_deref = deref_mixin<std::greater, T>;
template<class T> using my_comparator_deref = deref_mixin<my_comparator, T>;
// c++03
template<template<class> Op, class T>
struct deref_mixin {
bool operator()(const T &l, const T &r) const {
Op<T> op;
return op(*l, *r);
}
};
// Technically, the void template partial specialization isn't defined in c++03, but it should have been :)
template<template<class> Op>
struct deref_mixin<Op, void> {
template<class T, class U>
bool operator()(const T &l, const U &r) const {
Op<void> op;
return op(*l, *r);
}
};
template<class T> struct less_deref : deref_mixin<std::less, T> {};
As you said in your question if you inherit from std::less the you would get the three typedefs that are in std::less. What I like most about inheriting from it is it describes your intent. When I see
struct some_non_specific_name : std::less<some_type>
I know right there that this is a functor that is going to behave as an < for some_type. I don't have to read the struct body to find out anything.
As far as I can see, you are not missing any disadvantage. As you mentioned, you would automatically get the typedefs. The operator< has to be defined in both cases, and there is no difference in its implementation.
There is one thing that you might get that you might find neat, bad or just not applicable to your usecase (from here and here): there is a specialization of std::less for std::less<void> that has a template operator< deduces the return type of the operator< for the given arguments.
Unless you intend to use a SharedPtrContentsLess<void> (which probably doesn't make sense at all), both solutions would be equivalent.
I'd write a deref_less. First, my_less that smartly calls std::less:
struct my_less {
template<class Lhs, class Rhs,
class R = std::result_of_t< std::less<>( Lhs const&, Rhs const& ) >
// class R = decltype( std::declval<Lhs const&>() < std::declval<Rhs const&>() )
>
R operator()(Lhs const&lhs, Rhs const&rhs)const{
return std::less<>{}(lhs, rhs); // or lhs<rhs
}
// exact same type uses `std::less<T>`:
template<class T,
class R = std::result_of_t< std::less<>( T const&, T const& ) >
>
R operator()(T const& lhs, T const& rhs)const{
return std::less<T>{}(lhs, rhs);
}
template<class Lhs, class Rhs,
std::enable_if_t< std::is_base_of<Lhs, Rhs>{} && !std::is_same<Lhs, Rhs>{} >* = nullptr
>
bool operator()(Lhs const* lhs, Rhs const* rhs)const{
return std::less<Lhs const*>{}(lhs, rhs);
}
template<class Lhs, class Rhs,
std::enable_if_t< std::is_base_of<Rhs, Lhs>{} && !std::is_same<Lhs, Rhs>{} >* = nullptr
>
bool operator()(Lhs const* lhs, Rhs const* rhs)const{
return std::less<Rhs const*>{}(lhs, rhs);
}
template<class Lhs, class Rhs,
std::enable_if_t<
!std::is_base_of<Rhs, Lhs>{}
&& !std::is_base_of<Lhs, Rhs>{}
&& !std::is_same<Lhs, Rhs>{}
>* = nullptr
>
bool operator()(Lhs const* lhs, Rhs const* rhs)const = delete;
};
then, a deref_less that does a * then calls myless:
struct deref_less {
template<class Lhs, class Rhs,
class R = std::result_of_t< my_less( decltype(*std::declval<Lhs>()), decltype(*std::declval<Rhs>()) ) >
>
R operator()(Lhs const& lhs, Rhs const&rhs)const {
return my_less{}( *lhs, *rhs );
}
};
in C++14, but everything I used is easy to replace (std::less<> can be replaced with decltype and <s for example).
Because std::less lacks a virtual destructor (i.e. implicit destructor only), inheriting from it could technically lead to undefined behavior. Since neither type contains any data members, destruction should work no matter how the object is referenced, but the standard forbids polymorphic deletion through static destructors because it presents a strong possibility of problems (slicing, incomplete deletion) in most cases.
See this answer:
Thou shalt not inherit from std::vector
I have the following boost::variant type
using MyType = boost::variant<int, double, char, std::string, bool>;
and I would like to be able to use this type in as natural way as possible, in particular I'd like to be able to use the comparison operators such that comparison of types that would compile, give then correct result, otherwise behaviour is undefined (or an exception is thrown). For example suppose I have
MyType x {2}; // int
MyType y {1.0}; // double
MyType z {"hello"}; // std::string
I'd like to be able to compare x with y in the same way as comparing int {2} and double {1.0}. boost::variant already defined operator< etc, so I can make this comparison, but the result is not as expected.
cout << (x < y) << endl; // 1
cout << (y < x) << endl; // 0
I can define the desired behaviour using a boost::static_visitor
template <typename T, typename U, typename R = MyType>
using enable_if_both_arithmetic = std::enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value, R>;
template <typename T, typename U, typename R = MyType>
using enable_if_not_both_arithmetic = std::enable_if_t<!(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value), R>;
class is_less_than : public boost::static_visitor<bool>
{
public:
template <typename T>
bool operator()(const T& lhs, const T& rhs) const
{
return lhs < rhs;
}
template <typename T, typename U>
enable_if_both_arithmetic<T, U, bool> operator()(const T& lhs, const U& rhs) const
{
return lhs < rhs;
}
template <typename T, typename U>
enable_if_not_both_arithmetic<T, U, bool> operator()(const T& lhs, const U& rhs) const
{
return false; // or could throw
}
};
Which can be used like
cout << boost::apply_visitor(is_less_than(), x, y) << endl; // 0
but this is long and ugly. Is there someway I can 'overwrite' the boost::variant::operator< and use my own?
bool operator<(const VcfType& lhs, const VcfType& rhs)
{
return boost::apply_visitor(is_less_than(), lhs, rhs);
}
You are allowed to define a subclass containing the operator< you need, either of the boost::variant<int, double, char, std::string, bool> template instantiation (probably simpler) or of the boost::variant<> template (if you have other cases to cover).
I am in the process of converting a large set of geospatial code from one projection to another. To enforce proper units during this conversion, I have introduced Distance, Point, Rectangle, and Polygon templates which take a tag indicating what coordinate system is used. This is working out fairly well, but there are a lot of places where checks are performed for non-zero (!= 0) or positive values (> 0). I would like to be able to overload these operators to allow comparing against 0 without comparing against any other number. Is it possible to accomplish this?
As an additional restriction, I cannot use constexpr because I must support VS 2013, but I'd still be interested to hear if there is a way to do this with constexpr
Just for reference, I am working with something like this:
template<typename Tag> struct Distance
{
int value;
};
template<typename Tag> struct Point
{
Distance<Tag> x;
Distance<Tag> y;
};
// This works fine for comparing two Distances
template<typename Tag> bool operator>(const Distance<Tag>& a, const Distance<Tag>& b) {return a.value > b.value;}
// But I don't want this to allow a > 14, only a > 0
template<typename Tag> bool operator>(const Distance<Tag>& a, int b) {return a.value > b;}
struct Mercator;
typedef Point<Mercator> MercPoint;
struct GuiScale;
typedef Point<GuiScale> GuiPoint;
// etc.
You may use nullptr_t as a hack (as literal 0 convert to nullptr):
template<typename Tag> bool operator>(const Distance<Tag>& a, std::nullptr_t b) {return a.value > 0;}
You might use the conversion-to-any-pointer of a literal zero:
#include <type_traits>
template<typename Tag>
struct Distance
{
private:
using literal_zero = void(Distance::*)();
template<typename U>
using enable_nullptr = typename std::enable_if<
std::is_same< typename std::decay< U >::type, std::nullptr_t >::value
>::type;
public:
int value;
bool operator<( literal_zero ) const { return value < 0; }
template<typename U>
enable_nullptr<U> operator<( const U& ) const = delete;
};
int main() {
Distance<int> a;
a.value = 0;
a < 0;
// a < 42; // does not compile
// a < nullptr; // does not compile
}
This, unlike the other answer, also disallows a < nullptr. Also, if you remove the nullptr-related part and replace the using literal_zero = ... with a typedef, the same technique works with C++98.
Live example
If it's semantically valid to compare with a literal 0, it's valid to allow a conversion from literal 0 as well. With the conversion in place, you need no special case comparisons (Live at Coliru):
template<typename Tag> struct Distance
{
int value;
Distance() = default;
explicit constexpr Distance(int v) : value(v) {}
constexpr Distance(std::nullptr_t) : value(0) {}
friend constexpr bool operator == (const Distance& lhs, const Distance& rhs) {
return lhs.value == rhs.value;
}
friend constexpr bool operator < (const Distance& lhs, const Distance& rhs) {
return lhs.value < rhs.value;
}
// ...
};
Are there situations in which std::sort fails?
I've got a std::vector<KeyValPair<T>> queue with which I do the following
std::sort(queue.begin(), queue.end());
std::pair<iterator, iterator> match =
std::equal_range(queue.begin(), queue.end(), cost);
Exactly that. And then sometimes, not always, I get a "sequence not ordered" error.
The documentation describes sort and equal_range as using the same comparison functions, so I am confused how the vector could become unordered.
The vector type is the following class with custom comparison operators.
template<typename T>
class KeyValPair: public std::pair<double, T>
{
public:
KeyValPair(double d, T t): std::pair<double, T>(d, t){};
bool operator<(const KeyValPair<T>& rhs) const
{
return first < rhs.first;
}
bool operator==(const KeyValPair<T>& rhs) const
{
return second == rhs.second;
}
};
template<typename T>
bool operator< (const KeyValPair<T>& lhs, const double& rhs) {return lhs.first < rhs;};
template<typename T>
bool operator< (const double& lhs, const KeyValPair<T>& rhs) {return lhs < rhs.first;};
Could the comparison function be failing somehow? What else can cause this error?
As first psychically detected by #ecatmur, your problem is you are using < on doubles, and one or more of your doubles is a NaN.
A safe double ordering follows:
struct safe_double_order {
bool operator()(double lhs, double rhs) const {
if ((lhs != lhs) || (rhs != rhs)) // NaN detector
return (lhs!=lhs)>(rhs!=rhs); // order NaN less than everything, including -infinity
return lhs < rhs;
}
};
Next, we can write a key-sorter:
template<class K, class O=std::less<K>>
struct key_sorter {
struct helper {
K const& k;
helper( K const& o ):k(o) {}
template<typename V>
helper( std::pair<K, V> const& o ):k(o.first) {}
bool operator<( helper const& o ) const {
return O{}( k, k.o );
}
};
bool operator()( helper lhs, helper rhs ) const {
return lhs < rhs;
}
};
which passed a key-type and an optional ordering functor lets you search/sort std::pair<Key,?> with Key types directly.
std::vector< std::pair<double, X> > vec;
std::sort( vec.begin(), vec.end(), key_sorter<double, safe_double_order>{} );
auto match = std::equal_range( vec.begin(), vec.end(), value, key_sorter<double, safe_double_order>{} );
There are some C++11isms above, but the general design should be clear if you are using C++03.