// demonstration of common memory leak #include #include #include #include #include #include using namespace std; using namespace std::placeholders; const double conv = 45.0/atan(1.0); class GPScoords { public: virtual ~GPScoords() { } virtual void load(istream &is) { is >> lat >> lon; lat /= conv; lon /= conv; } virtual void save(ostream &os) const { os << lat*conv << ' ' << lon*conv; } double distance(const GPScoords &gps) const { return acos(sin(lat)*sin(gps.lat) + cos(lat)*cos(gps.lat)*cos(lon-gps.lon))*6371.0; } private: double lat, lon; }; class GPStag : public GPScoords { public: virtual ~GPStag() { } virtual void load(istream &is) { GPScoords::load(is); is >> mytag; } virtual void save(ostream &os) const { GPScoords::save(os); os << ' ' << mytag; } void settag(const string &s) { mytag = s; } string tag() const { return mytag; } // prefer this to returning // "const string &" as this return can bind to an rval ref private: string mytag; }; typedef unique_ptr GPSptr; GPSptr loadGPS(istream &is) { char c; is >> c; GPSptr ret; if (c=='T') ret = GPSptr(new GPStag()); else { is.putback(c); ret = GPSptr(new GPScoords()); } ret->load(is); return ret; } int main(int argc, char **argv) { fstream file; file.exceptions(ifstream::eofbit); vector locs; shared_ptr center; try { file.open(argc>1 ? argv[1] : "testgps2.txt"); int n; file >> n; if (n) center = loadGPS(file); for(int i=1;isave(cout); cout << endl; // This is the way I would write the lambda expression: sort(locs.begin(),locs.end(), [¢er](const GPSptr &p1, const GPSptr &p2) { return p1->distance(*center) < p2->distance(*center); } ); // but here are some other ways of achieving the same affect, // just to show currying... auto closerto = [](const shared_ptr &x, const GPSptr &y1, const GPSptr &y2) { return x->distance(*y1) < x->distance(*y2); }; // Bind version 1: // bind: (bind copies -- or so it seems -- , so center must be copiable) // some reference suggest it should be able to move, but // at least g++ 4.7 doesn't allow that /* sort(begin(locs),end(locs),std::bind(closerto,center,_1,_2)); */ // currying via a lambda expression: /* sort(begin(locs),end(locs),[=](const GPSptr &y1, const GPSptr &y2) { return closerto(center,y1,y2); } ); */ // Bind version 2: (example using non-static member function) /* auto disttoc = std::bind(&GPScoords::distance,center.get(),_1); sort(begin(locs),end(locs),[disttoc](const GPSptr &y1, const GPSptr &y2) { return disttoc(*y1) < disttoc(*y2); }); */ for(auto &x : locs) { // need & here (otherwise, asking for copy of ptr) x->save(cout); cout << endl; } }