====== Function Objects ή Functors ====== Συχνά στην STL θέλουμε να εφαρμόσουμε μία συνάρτηση πάνω στο περιεχόμενο ενός //container// προκειμένου να μεταβάλλουμε το περιεχόμενο του ή να αποθηκεύσουμε το αλλαγμένο περιεχόμενο σε ένα διαφορετικό από το αρχικό //container//. ===== Η συνάρτηση for_each ===== Η συνάρτηση [[http://www.cplusplus.com/reference/algorithm/for_each/|std::for_each]] επιτρέπει την μεταβολή του περιεχομένου ενός //container// από //first// έως //last// (μη συμπεριλαμβανομένου) από τη συνάρτηση //fn//. Η υλοποίηση της συνάρτησης δίνεται παρακάτω: template Function for_each(InputIterator first, InputIterator last, Function fn) { while (first!=last) { fn (*first); ++first; } return fn; // or, since C++11: return move(fn); } Παρακάτω δίνεται ένα παράδειγμα, όπου στα περιεχόμενα ενός ''vector'' προστίθεται το //prefix// "light" με τη βοήθεια της συνάρτησης //prefixMe//: #include #include #include using namespace std; template void print(vector v) { for(auto it = v.cbegin(); it!=v.cend(); it++) cout << *it << ", "; cout << endl; } void prefixMe(string& str) { str = "light " + str; } int main() { vector colors; colors.push_back("red"); colors.push_back("green"); colors.push_back("blue"); print(colors); for_each(colors.begin(), colors.end(), prefixMe); print(colors); } ==== Χρήση ενός function object αντί για συνάρτηση ==== Παρατηρήστε ότι ο κώδικας δουλεύει σωστά, με την υποσημείωση ότι κάθε φορά που θέλετε να αλλάξετε το prefix το οποίο προστίθεται στα περιεχόμενα του //container// πρέπει να γράφετε μία νέα συνάρτηση. Αντί για αυτό θα μπορούσαμε να χρησιμοποιήσουμε ένα αντικείμενο ως συνάρτηση το οποίο να έχει τα εξής χαρακτηριστικά: - διαθέτει ένα πεδίο το οποίο περιέχει το prefix που θα προστεθεί. - υπερφορτώνει τον τελεστή () (//operator()//) με ένα μόνο όρισμα τύπου //std::string//, ώστε να μπορούμε να το χρησιμοποιήσουμε ως συνάρτηση. Ένα τέτοιο αντικείμενο ονομάζεται //function object ή functor//. Δείτε το παρακάτω παράδειγμα όπου ορίζουμε την κλάση //PrefixString//, η οποία λαμβάνει στον κατασκευαστή της ένα std::string που θα αποτελέσει το //prefix//. Με βάση τον παρακάτω κώδικα, χρησιμοποιώντας αντικείμενα της συγκεκριμένης κλάσης ως συναρτήσεις, μπορούμε να καλέσουμε διαφορετικές εκδόσεις της συνάρτησης που προσθέτει το //prefix//, απλά αλλάζοντας την παράμετρο στον κατασκευαστή της. #include #include #include using namespace std; template void print(vector v) { for(auto it = v.cbegin(); it!=v.cend(); it++) cout << *it << ", "; cout << endl; } class PrefixString { string prefix; public: PrefixString(string p): prefix(p) {} void operator()(string& str) { str = prefix + str; } }; int main() { vector colors; colors.push_back("red"); colors.push_back("green"); colors.push_back("blue"); print(colors); for_each(colors.begin(), colors.end(), PrefixString("light ")); print(colors); }