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
Next revision Both sides next revision
cpp:functors [2020/06/01 04:25]
cpp:functors [2020/06/01 05:20]
gthanos [Η συνάρτηση for_each]
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//, η οποία δημιουργεί ένα //function object//.
 +
 +<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)