User Tools

Site Tools


cpp:functors

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Previous revision
cpp:functors [2020/06/01 04:25]
cpp:functors [2020/06/01 05:25]
gthanos [Χρήση ενός function object αντί για συνάρτηση]
Line 1: Line 1:
 +====== Function Objects ή Functors ======
 +
 +Συχνά στην STL θέλουμε να εφαρμόσουμε μία συνάρτηση πάνω στο περιεχόμενο ενός //container// προκειμένου να μεταβάλλουμε το περιεχόμενο του ή να αποθηκεύσουμε το αλλαγμένο περιεχόμενο σε ένα διαφορετικό από το αρχικό //container//.
 +
 +===== Η συνάρτηση for_each =====
 +
 +Η συνάρτηση [[http://www.cplusplus.com/reference/algorithm/for_each/|std::for_each]] επιτρέπει την μεταβολή του περιεχομένου ενός //container// από //first// έως //last// (μη συμπεριλαμβανομένου) από τη συνάρτηση //fn//. Η υλοποίηση της συνάρτησης δίνεται παρακάτω:
 +<code cpp>
 +template<class InputIterator, class Function>
 +  Function for_each(InputIterator first, InputIterator last, Function fn) {
 +  while (first!=last) {
 +    fn (*first);
 +    ++first;
 +  }
 +  return fn;      // or, since C++11: return move(fn);
 +}
 +</code>
 +
 +Παρακάτω δίνεται ένα παράδειγμα, όπου στα περιεχόμενα ενός ''vector<string>'' προστίθεται το //prefix// "light" με τη βοήθεια της συνάρτησης //prefixMe//:
 +
 +<code cpp prefix_str.cpp>
 +#include <vector>
 +#include <algorithm>
 +#include <iostream>
 +
 +using namespace std;
 +
 +template<typename T>
 +void print(vector<T> v) {
 +  for(auto it = v.cbegin(); it!=v.cend(); it++) 
 +    cout << *it << ", ";
 +  cout << endl;
 +}
 +
 +void prefixMe(string& str) {
 +  str = "light " + str;
 +}
 +
 +int main() {
 +  vector<string> colors;
 +  
 +  colors.push_back("red");
 +  colors.push_back("green");
 +  colors.push_back("blue");
 +  
 +  print(colors);
 +  for_each(colors.begin(), colors.end(), prefixMe);
 +  print(colors);
 +}
 +</code>
 +
 +==== Χρήση ενός function object αντί για συνάρτηση ====
 +
 +Παρατηρήστε ότι ο κώδικας δουλεύει σωστά, με την υποσημείωση ότι κάθε φορά που θέλετε να αλλάξετε το prefix το οποίο προστίθεται στα περιεχόμενα του //container// πρέπει να γράφετε μία νέα συνάρτηση. Αντί για αυτό θα μπορούσαμε να χρησιμοποιήσουμε ένα αντικείμενο ως συνάρτηση το οποίο να έχει τα εξής χαρακτηριστικά:
 +  - διαθέτει ένα πεδίο το οποίο περιέχει το prefix που θα προστεθεί.
 +  - υπερφορτώνει τον τελεστή () (//operator()//) με ένα μόνο όρισμα τύπου //std::string//, ώστε να μπορούμε να το χρησιμοποιήσουμε ως συνάρτηση.
 +
 +Ένα τέτοιο αντικείμενο ονομάζεται //function object ή functor//. Δείτε το παρακάτω παράδειγμα όπου ορίζουμε την κλάση //PrefixString//, η οποία λαμβάνει στον κατασκευαστή της ένα std::string που θα αποτελέσει το //prefix//. Με βάση τον παρακάτω κώδικα, χρησιμοποιώντας αντικείμενα της συγκεκριμένης κλάσης ως συναρτήσεις, μπορούμε να καλέσουμε διαφορετικές εκδόσεις της συνάρτησης που προσθέτει το //prefix//, απλά αλλάζοντας την παράμετρο στον κατασκευαστή της.
 +
 +<code cpp prefix_str_function_object.cpp>
 +#include <vector>
 +#include <algorithm>
 +#include <iostream>
 +
 +using namespace std;
 +
 +template<typename T>
 +void print(vector<T> 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<string> 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);
 +}
 +</code>
 +
  
cpp/functors.txt · Last modified: 2020/06/01 04:25 (external edit)