I want to sort some vector depending on an element's member function value like this:
std::vector<cv::Rect> regions;
std::sort(begin(regions), end(regions), [](cv::Rect const& l, cv::Rect const& r){
return l.area() > r.area();
});
Can I do it without directly writing the comparison? I can imagine something like:
std::sort(begin(regions), end(regions), std::compare_greater<cv::Rect::area>);//imaginary code
Is there something like this?
Edit:
cv::Rect::area is a member function that returns float. cv::Rect does not have a comparison operator or, it has one but I want to sort based on another one.
Following on from the comments on the OP; you can refactor the lambda into its own functor for use the std::sort, or you could use a C++03 style by combining the std::greater, std::mem_fun with a bind (possibly std::bind) of some sort etc.; the C++03 style will be cumbersome to work with though.
The functor solution requires the call operator (operator()) to have the appropriate signature; accept the required values and return a bool, the const method and const& parameters are not needed, but by convention usually appear.
struct compare_rect_greater {
bool operator()(cv::Rect const& l, cv::Rect const& r) const
{
return l.area() > r.area();
}
};
// ...
std::vector<cv::Rect> regions;
std::sort(begin(regions), end(regions), compare_rect_greater());
The float return from the area() function will work as expected with the operator >.
But considering the language level, ease of readability etc. your lambda is possible still the better solution.
std::vector<cv::Rect> regions;
std::sort(begin(regions), end(regions), [](cv::Rect const& l, cv::Rect const& r){
return l.area() > r.area();
});
The C++03 style is unwieldily to create and use in this case, I would not venture too far down this road.
You may create a class for that:
template <typename Member>
struct greater_member;
template <typename C, typename Method>
class greater_member<Method (C::*)>
{
explicit greater_member(Method (C::* method)) : mMethod(method) {}
bool operator()(const C& lhs, const C& rhs) const
{
return (lhs.*mMethod)() > (rhs.*mMethod)();
}
private:
Method (C::* mMethod);
}
template <typename C, typename Method>
greater_member<Method (C::*)> make_greater_member(Method (C::* method))
{
return greater_member<Method (C::*)>(method);
}
And then
std::sort(begin(regions), end(regions), make_greater_member(&cv::Rect::area));
Demo
Related
In order to use a standard function like std::sort on some standard container Container<T>
struct T{
int x,y;
};
based on the y value, you need to write something like (for example):
std::vector<T> v;
//fill v
std::sort(v.begin(),v.end(),[](const auto& l,const auto& r){
return l.y<r.y;
});
The comparer that was written as lambda function is used too much and re-written again and again during the code for various classes and attributes.
Considering the case where y's type is comparable (either like int or there is an overload for the < operator), is there any way to achieve something like:
std::sort(v.begin(),v.end(),imaginary::less(T::y)); // Imaginary code
Is it possible in C++ to write such a function like less? or anything similar?
I am asking because I remember something like that in some managed language (I am not sure maybe C# or Java). However, I am not sure even about this information if it is true or not.
template<typename T, typename MT>
struct memberwise_less
{
MT T::* const mptr;
auto operator()(const T& left, const T& right) const
{ return (left.*mptr) < (right.*mptr); }
};
template<typename T, typename MT>
memberwise_less<T, MT> member_less(MT T::*mptr)
{
return { mptr };
}
and then you can do
std::sort(v.begin(), v.end(), member_less(&T::y));
I need to use different compare functions as unary functions, where one of the values is embedded inside the comparator. To do so I created an adaptor class, something like:
template<typename T, typename Compare>
class CompareAdaptor : private Compare
{
public:
CompareAdaptor(T value)
: mValue(value)
{
}
bool operator()(T v) const
{
return Compare::operator()(v, mValue);
}
private:
T mValue;
};
and now I can define a new unary comparator like:
template<typename T>
using EqualTo = CompareAdaptor<T, std::equal_to<T>>;
template<typename T>
using LessEqual = CompareAdaptor<T, std::less_equal<T>>;
My questions is: Is there a simpler way(without using the adaptor class) to define those unary comparators? I think this is a very common problem and probably you have better solutions.
In C++11, this is as good as it gets. But I'd rather expect the predicate to be directly constructed at the call site :
std::find_if(begin(v), end(v), [limit](int i) { return i < limit; });
In C++14, you could use return type deduction to make a factory fuction :
template <class Comp>
auto predicate(typename Comp::second_argument_type rhs) {
return [c = Comp{}, rhs](typename Comp::first_argument_type lhs) {
return c(lhs, rhs);
};
}
Example call : predicate<std::less<int>>(4) returns the function object.
Live on Coliru
#Quentins answer can also be made compilable in C++11 using std::function as the return type which the lambdas are convertible to:
template <class Comp>
std::function<typename Comp::result_type (typename Comp::first_argument_type)> predicate(typename Comp::second_argument_type rhs)
{
return [rhs](typename Comp::first_argument_type lhs){
Comp c{};
return c(lhs, rhs);
};
}
live on coliru
C++ How to Sort Vector making use of Template
Hi Guys, thanks for looking at my question.
I got a Templates.h file that goes this way..
/* Template Less Than */
template<typename T>
bool lessThan(T a,T b)
{
return a<b;
}
/* Template greater Than */
template<typename T>
bool greaterThan(T a,T b)
{
return a>b;
}
/* Template Equals */
template<typename T>
bool equals(T a,T b)
{
return a==b;
}
Then i got this class
Map2D
About Map2D..
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
};
At my main.cpp i got a vector class of Map2D
vector<Map2D> map2d;
So now i need to sort it by X Ascending.. how do i make use of the template file to do a sort on the vector of it X Ascending.. Consider i will need overload another for DESCENDING later..
Normally i will use
sort(map2d.begin(),map2d.end(),sortByX);
and sortByX will be a struct with overload by it () operator.
But the question now is since i got a template that is lesser than and greater than.. how can i make use of it to sort X by ascending and then another X by descending with the template generic function of Templates.H .
Updates:
I think i need to overload the class Map2D operator > , < and ==
but my question is how do i overload it with the help of MyTemplates.h function such as lesserThan , greaterThan, equals
Thanks.
Define a comparator for your class or simpler, a operator<() overload (which you need to do anyway for your templates to work).
First, fix your templates:
template<typename T>
bool lessThan(const T& a, const T& b)
{
return a<b;
}
template<typename T>
bool greaterThan(const T& a, const T& b)
{
return b<a;
}
template<typename T>
bool equals(const T& a, const T& b)
{
return !(a<b || b<a);
}
Next, define an operator<() on your class.
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
// this sample sorts on X dominantly, and Y if X is the same
bool operator <(const Map2D& obj) const
{
return (x < obj.x || (x == obj.x && y < obj.y));
};
}
Now just invoke sort:
std::sort(map2d.begin(), map2d.end());
Invoke using your lessThan template as such:
std::sort(map2d.begin(), map2d.end(), lessThan<Map2D>);
Or your greaterThan template:
std::sort(map2d.begin(), map2d.end(), greaterThan<Map2D>);
In C++11 you could write a lambda function to do it.
Using boost, if you want a "one-step on the fly" functor it would have to be something like:
bind( less<int>, bind(&Map2D::getX(),_1), bind(&Map2D::getX(),_2) )
// or your lessThan<int> which already exists in C++ as less<int>
Not sure if that will work exactly. (Will the 2nd and 3rd binds convert properly to placeholders?) Easier to write a very generic functor that combines what you are trying to do, i.e. extract something from your class (a transformation) then pass that into the predicate.
template< typename Trans, typename Pred >
struct Comparator
{
Comparator( Trans t , Pred p ) : trans( t ), pred ( p )
{
}
template< typename T >
bool operator()( T const& t1, T const& t2 ) const
{
return pred( trans(t1), trans(t2) );
}
private:
Trans trans;
Pred pred;
};
template< typename Trans, typename Pred >
Comparator< Trans, Pred > makeComparator( Trans t, Pred p )
{
return Comparator( t, p );
}
// then in your code
std::sort( map2d.begin(), map2d.end(),
makeComparator( boost::bind( &Map2D::getX(), _1 ), lessThan<int> ) );
should work and you've kept Comparator generic.
(Not sure if boost already offers something like this).
There are a few issues with your code:
Class is missing semicolon at the end.
Your comparison templates should return bool instead of a T.
You miss comparison operators inside your class:
bool operator<(const Map2D &m) const {return /* some code here */ }
bool operator>(const Map2D &m) const {return /* some code here */ }
bool operator==(const Map2D &m) const {return /* some code here */ }
or fix your templates to only use operator<() for all the comparisons (which is a common practice BTW).
When you fix above you just use your templates like that:
sort(map2d.begin(),map2d.end(), lessThan<Map2D>);
sort(map2d.begin(),map2d.end(), greaterThan<Map2D>);
BTW, you do not need custom templates to sort your class in such an easy way. Reuse what is already in STL:
sort(map2d.begin(),map2d.end()); // less
sort(map2d.begin(),map2d.end(), std::greater<Map2D>());
You can find those in functional header. You also cannot use operator==() for sorting but it may be useful for unordered containers introduced in C++11.
EDIT: If your sorting algorithms for Map2D class are fixed (what is lessThan does not change with time) than I suggest following my answer. Otherwise if now you want to sort by X and after a few lines by Y than #MikeSeymour answer may be better suited to your needs.
If you are in C++11, you can write something like this:
std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
return lessThan(a.getX(), b.getX()); } ); // accending
std::sort(map2d.begin(), map2d.end(), [](const Map2D& a, const Map2D& b) {
return greaterThan(a.getX(), b.getX()); }); // decending
Otherwise you have to implement compare functor, i.e
struct compare
{
bool operator () (const Map2D& a, const Map2D& b)
{
return lessThan(a.getX(), b.getX());
}
};
and then
std::sort(map2d.begin(), map2d.end(), compare());
But really it isn't a good style to have lessThan, greaterThan, since you can compare x directly. And if you want some special comparison for Map2D maybe it is better to make these compare functions only for Map2D objects.
Upd: you can also use just function pointer as your comparator, i.e:
bool compare(const Map2D& a, const Map2D& b)
{
return lessThan(a.getX(), b.getX());
}
and then
std::sort(m.begin(), m.end(), compare);
But you may loss some performance (see comments below).
You first need to overload operators <, > and == to use Map2D with your templates:
class Map2D
{
protected:
int x;
int y;
public:
Map2D();
Map2D(int,int);
int getX();
int getY();
bool operator<(const Map2D& other)const //less then
{
return x < other.x;
}
//other operators is same manner
}
After you have done you just use it:
sort(map2d.begin(),map2d.end(),lessThan<Map2D>);
You can't really. You'll need to define functors (either functions, or classes that overload operator() appropriately) to do the particular object-member comparisons you need, and your function templates don't do that. You need something like:
struct compare_x_less {
// NOTE: you'll need to declare `get_X() const` for this to work.
// You should do that anyway.
bool operator()(Map2D const & a, Map2D const & b) {
return a.get_X() < b.get_X();
}
};
// and similarly for `compare_x_greater` and any other comparisons you need
std::sort(map2d.begin(),map2d.end(),compare_x_less());
In C++11, lambdas can save you a bit of typing:
std::sort(map2d.begin(),map2d.end(),[](Map2D const & a, Map2D const & b) {
return a.get_X() < b.get_X();
});
sort(map2d.begin(),map2d.end(),lessThan<map2d>);
Be aware that lessThan is a prediacte function that should return instead of T value of type bool
Some additional explanation:
// usage
/* Some moments to mention: if you omit third argument, default argument less<T> will be used,
which is enough for built-in types, also you can use predicates already defined in STL:
greater<T>, less<T> or you can provide your own predicate */
sort(map2d.begin(),map2d.end(),lessThan<map2d>);
// header file, where we define predicats which we shall provide as argument to algorithm sort
// predicate expected by function sort has to obey the following rules:
// 1. return bool 2. accept 2 parameters
/*2 variants of predicat*/
// 1) operator< is overloaded for class T, so we can use it to compare instances of that class
template<typename T>
bool lessThan(T a,T b)
{
return a < b;
}
/* 2) operator< not overloaded, when we have to get values of class members by which we are going to compare them
this could be done in various ways, for ex. by means of getters();*/
template<typename T>
bool lessThan(T a,T b)
{
return a.getValueOfMember() < b.getValueOfMember();
}
A good way, I don't think it's the best.
You can overload the operator (<) & (!=) in the class. If you only want to sort for X.
And just use sort(map2d.begin(), map2d.end()) for ascending. and sort(map2d.rbegin(), map2d.rend()) for descending .. And that solves your problem.
OR:
You can make 2 functions to compare 1 relevant to x & the other relevant to Y.
As:
int cmpx(const void* A, const void *B){
Map2D a = *(Map2D *)A;
Map2D b = *(Map2D *)B;
if(a.x < b.x) return -1;
if(a.x == b.x) return 0;
return 1;
}
// And use
qsort(map2d.begin(), (int)map2d.size(), sizeof(Map2D), cmpx);
And so for Y.
Not sure if map2d.rbegin() will sort this descedingly or you'll have to do it on your own as well.
I have been trying to understand this code
template <typename T, typename _Prd = equal_to<T> >
struct Vector3
{
protected:
T i,j,k;
_Prd comp;
public:
//default constructor
Vector3(void);
//explicit constructor
Vector3(const T& ijk);
//explicit constructor
Vector3(const T& i,const T& j,const T& k);
//copy constructor
Vector3(const Vector3<T,_Prd>& copy_from);
//getters
T I() const;
T J() const;
T K() const;
//setters
void I(const T& i);
void J(const T& j);
void K(const T& k);
//get magnitude of vector.
T Magnitude() const;
//angle between I,J (clockwise)
T Direction() const;
//angle between K and I,J
T Elevation() const;
//scale vector to 1
Vector3<T,_Prd>& Normalize();
//vector scale up-to value
Vector3<T,_Prd>& Scale(const T& length);
...
};
I can't understand first statement
template <typename T, typename _Prd = equal_to<T> > struct Vector3 {};
It's about the usage of equal_to<T>, I found the reference from here and here. But still there isn't anything like this. Thank you for any help to make me understand this part.
Update:
After seeing the answers and reading some text book, my question turns to 2 aspects.
1. Default Template Arguments
In C++11 we can supply default template arguments to a template.
Example from C++ primer 5th ed. Page 670.
#include <functional>
template <typename T, typename F = less<T> >
int compare (const T &v1, const T &v2, F f = F() )
{
if (f(v1, v2) return -1 ;
if (f(v2, v1) return 1 ;
return 0 ;
}
And then we use this template as:
bool i = compare(0,42) ;
The template will use default less function-object class to instantiate.
However, when we use our own objects:
Sales_data item(cin), item2(cin) ;
bool j = compare (item, item2, compareIsbn) ;
Then F turns to compareIsbn function-object instead.
So that the same happens on my question above, this way will leave an entrance to the user of the template to allow them introducing their own function-object, in this case it is used as comparator.
2. Predicates
Check What is predicate in C++?
std::equal_to is a class template, which provides something like this:
bool operator()(T const & lhs, T const & rhs) const { return lhs == rhs; }
In other words, it's a function-object class that wraps the ordinary == comparator. The point is that equal_to can be specialized, and thus provides a non-intrusive way of adding customizability.
On top of that, your template Vector3 also provides an intrusive way of customizing the comparator by way of the second template argument.
Note that predicates are typically objects, and not just trait classes. So your container will actually contain a predicate subobject. If the predicate class is default-constructible, this is no problem, but if it isn't then you must normally provide a copy of the predicate in the container constructor.
As a homework assignment, you can think about how you can avoid spending any actual memory on the predicate subobject.
The second template argument _Prd is assigned a default type much like a function can have default values for arguments. STL uses this heavily. have a look at std::basic_string as an example
I'm building a series of predicates that duplicate lots of code, and so are being changed into a single template function class based on the std::unary_function. The idea is that my class interface requires methods such as Element_t Element() and std::string Name() to be defined, so the predicate template arguments are the object type and a value type to which comparison will be made as follows:
// generic predicate for comparing an attribute of object pointers to a specified test value
template <class U, typename R>
class mem_fun_eq : public std::unary_function <U*, bool> {
private:
typedef R (U::*fn_t)();
fn_t fn;
R val;
public:
explicit mem_fun_eq (fn_t f, R& r) : fn(f), val(r) { }
bool operator() (U * u) const {
return (u->*fn)() == val;
}
};
Thus, if I have:
class Atom {
public:
const Element_t& Element() const { return _element; }
const std::string& Name() const { return _name; }
};
I would like to perform a search on a container of Atoms and check for either the Name or Element equality using my template predicate like so:
typedef std::string (Atom::*fn)() const;
Atom_it it = std::find_if( _atoms.begin(), _atoms.end(), mem_fun_eq <Atom, std::string> ((fn)&Atom::Name, atomname));
but compiling this returns the following error on the std::find_if line:
error: address of overloaded function with no contextual type information
Also, trying to form the same predicate for a check of the Element() as such:
typedef Atom::Element_t& (Atom::*fn)() const;
Atom_it it = std::find_if(_atoms.begin(), _atoms.end(), mem_fun_eq <Atom, Atom::Element_t> ((fn)&Atom::Element, elmt);
creates a different error!
error: no matching function for call to ‘mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(Atom::Element_t& (Atom::*)()const, const Atom::Element_t&)’
note: candidates are: mem_fun_eq<U, R>::mem_fun_eq(R (U::*)(), R&) [with U = Atom, R = Atom::Element_t]
note: mem_fun_eq<Atom, Atom::Element_t>::mem_fun_eq(const mem_fun_eq<Atom, Atom::Element_t>&)
Firstly, am I reinventing the wheel with this predicate? Is there something in the STL that I've missed that does the same job in a single class? I can always break the predicate down into several more specific ones, but I'm trying to avoid that.
Secondly, can you help me with the compiler errors?
I don't know of any easy way to do this using the bits provided with the STL. There is probably some clever boost way, using iterator adapters, or boost::lambda, but personally I wouldn't go that way.
Obviously C++0x lambdas will make all this easy.
Your problem is attempting to cast a function like this:
const std::string&(Atom::*)()
into a function like this:
std::string (Atom::*)()
If you replace your typedef R (U::*fn_t)(); with typedef const R& (U::*fn_t)() const; then it should work.
The following avoids this problem and also provides type inference so that you can just write mem_fun_eq(&Atom::Name, atomname). It compiles for me, although I haven't tested it.
template<typename U, typename R, typename S>
class mem_fun_eq_t : public std::unary_function<U const*, bool>
{
private:
R (U::*fn_)() const;
S val_;
public:
mem_fun_eq_t(R (U::*fn )() const, S val) : fn_(fn), val_(val){}
bool operator()(U * u)
{
return (u->*fn_)() == val_;
}
};
template<typename U, typename R, typename S>
mem_fun_eq_t<U, R, S> mem_fun_eq(R (U::*fn)() const, S val)
{
return mem_fun_eq_t<U, R, S>(fn, val);
}
Have you thought of trying to mix in a mem_fun_ref or mem_fun object in place of the member function call?
Basically, you call on mem_fun to create an object that accepts two arguments T* and a template argument to the function A if it has one (or void if it doesn't). Hence you combine it like so:
template<typename MemFunc, typename CompareType, typename T>
struct MyPredicate{
MyPredicate(MemFunc _functionObj, CompareType _value)
: m_Value(_value),
m_Function(_functionObj){}
bool operator()(const T &_input){
return m_Value == m_Function(_input);
}
private:
MemFunc m_Function;
CompareType m_Value;
};
Edit:
Ok, that's not completely working so why not have:
struct NamePred: binary_function<Atom*,string,bool>{
bool operator()(Atom *_obj, string _val){
return _obj->Name() == _val;
};
};
then use bind2nd
find_if( atoms.begin(), atoms.end(), bind2nd( NamePred, "yo" ) );