简体   繁体   中英

C++ std::sort custom compare function referencing to another list

I am a beginner in C++ and I don't know nor can find the way to address my problem.

I'm trying to sort my vector in an unusual way and fail to do so.

pointsToVisit - list of Point objects that can have their start time and end time.

visitedPoints - list of indexes of Point objects from pointsToVisit vector

I'd like to sort my visitedPoints vector by values of respective Points

BeeHive
    std::vector<Point> pointsToVisit;
    std::vector<Route> routes;

Route
    std::vector<int> visitedPoints;

My attemp is below:

bool BeeHive::isPointsVisitStartPrior (int i, int j) { return (pointsToVisit.at(i).startTime<pointsToVisit.at(j).startTime); }

Route BeeHive::sortRouteByStartTime(int routeIndex){
    Route route2 = Route();
    route2.setStartTime(routes.at(routeIndex).getStartTime());
    route2.setVisitedPoints(routes.at(routeIndex).getVisitedPoints());
    std::sort(route2.getVisitedPoints().begin()+1, route2.getVisitedPoints().end(), isPointsVisitStartPrior);
    evaluateRoute(route2);
    return route2;
}

And I get such errors:

Error   5   error C3867: 'BeeHive::isPointsVisitStartPrior': function call missing argument list; use '&BeeHive::isPointsVisitStartPrior' to create a pointer to member c:\vrp projekt\vrp\vrp\beehive.cpp  193 1   VRP
Error   6   error C2780: 'void std::sort(_RanIt,_RanIt)' : expects 2 arguments - 3 provided c:\vrp projekt\vrp\vrp\beehive.cpp  193 1   VRP

Example by which I tried to do my work is under this address: http://www.cplusplus.com/reference/algorithm/sort/

I'll be thankful for any help received.


Might it be possible, that creating bubble sort for my own purposes will substitute std::sort() decently?

isPointsVisitStartPrior is a member function, this cannot be used directly in sort. You have to either use a global function or a function-object.

If you have access to C++ 11 features, you can use a lambda:

std::sort(route2.getVisitedPoints().begin()+1, route2.getVisitedPoints().end(), 
[&](int i, int j){ return isPointsVisitStartPrior(i, j);  });

You can also make a functor object with an operator() , something like

class VisitedPointsCompararer {
public:
   VisitedPointsCompararer(const std::vector<Point>& pointsToVisit): pointsToVisit(pointsToVisit) {
   }


   bool operator() (int i, int j) {
      return pointsToVisit.at(i).startTime < pointsToVisit.at(j).startTime;
   }

...

private:
   const std::vector<Point>& pointsToVisit;
}

isPointsVisitStartPrior(int, int) is a member function. A such, while it looks like it takes two arguments, it really implicitly takes three: it also needs a BeeHive* on which to operate (the this pointer).

What you need to do is "bind" the BeeHive* to the call:

using namespace std::placeholders;
std::sort(route2.getVisitedPoints().begin()+1, 
          route2.getVisitedPoints().end(), 
          std::bind(&BeeHive::isPointsVisitStartPrior, this, _1, _2)
     //   ^^^^^^^^^ without C++11, there's also boost::bind
);

That will save off this as the first argument in the call to the three-argument function, and forward the next two arguments you call it with into the next two slots.

This is logically equivalent to:

std::sort(route2.getVisitedPoints().begin()+1, 
          route2.getVisitedPoints().end(), 
          [this](int i, int j){ return isPointsVisitStartPrior(i, j); }
);

Though with the lambda, the compiler may be able to inline the call for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM