Misreference Pointers

There are times when one has pointers in the STL container and where less than the comparison should not be performed by the pointer, but by the objects that it points to. A simple example is a vector that should be sorted by real numbers. I am currently solving this with:

template<class T_PTR> struct ltDeref { bool operator()(T_PTR p0,T_PTR p1) const {return *p0<*p1;} }; 

and use it as

 vector<double*> vIn; sort(vIn.begin(),vIn.end(),ltDeref<double*>()); 

or

 set<double*,ltDeref<double*> > someSet; 

Instead of writing my own comparison function, is there a more β€œstandard” way in C ++ that does not require a user-created template?

+4
source share
2 answers

Often you can use the functors available in functional to build the resulting sort functor exclusively from standard constructs.

But there is no dereference of the T* pointer, so you have to use your own comparator.


The closest thing you can get is when your "pointer type" is not primitive, but some User-Defined-Type with operator* , which can be solved.

The following code is C ++ 11 (for using std::bind , which is simpler than std::bind1st and std::bind2nd ).

 #include <vector> #include <algorithm> #include <functional> #include <iostream> // Fakes a "smart pointer" wrapper around data template <typename T> struct Ptr { Ptr(T data) : data(data) {}; const T& operator*() const { return data; } private: T data; }; int main() { std::vector<Ptr<double>> vIn; vIn.push_back(Ptr<double>(5)); vIn.push_back(Ptr<double>(2)); vIn.push_back(Ptr<double>(6)); using namespace std::placeholders; std::sort( vIn.begin(), vIn.end(), std::bind( std::less<double>(), std::bind(&Ptr<double>::operator*, _1), std::bind(&Ptr<double>::operator*, _2) ) ); std::vector<Ptr<double>>::const_iterator it = vIn.begin(), end = vIn.end(); for ( ; it != end; ++it) std::cout << ',' << **it; } 

Thus, if instead of double* you have std::unique_ptr<double> or std::shared_ptr<double> , this might work:

 #include <vector> #include <memory> #include <algorithm> #include <functional> #include <iostream> int main() { typedef std::unique_ptr<double> STDUPD; std::vector<STDUPD> vIn; vIn.push_back(STDUPD(new double(5))); vIn.push_back(STDUPD(new double(2))); vIn.push_back(STDUPD(new double(6))); using namespace std::placeholders; std::sort( vIn.begin(), vIn.end(), std::bind( std::less<double>(), std::bind(&STDUPD::operator*, _1), std::bind(&STDUPD::operator*, _2) ) ); std::vector<STDUPD>::const_iterator it = vIn.begin(), end = vIn.end(); for ( ; it != end; ++it) std::cout << ',' << **it; } 

Another reason to avoid raw pointers if you can ...

+1
source

There is no ready-made solution, as other answers say. The dereferencing comparator of source pointers can be slightly improved if it is available only for raw-pointer types with the following explicit template specification. I expect this to give somewhat better error messages from the compiler when using a non-pointer type.

 template<class T> struct PointeeLess; template<class T> struct PointeeLess<T const *> { bool operator()( T const * a , T const * b ) const { return *a < *b; } }; 

OTOH, the template in question will work for types without raw pointers that implement the * operator.

0
source

All Articles