C++ Tutorial/Development/Functor

Материал из C\C++ эксперт
Перейти к: навигация, поиск

Demonstrating function pointer passing

<source lang="cpp">//Revised from //STL Tutorial and Reference Guide C++ Programming with the Standard Template L ibrary, 2nd Edition //by David R. Musser (Author), Atul Saini (Author) //# Publisher: Addison-Wesley Pub (Sd) (March 1996) //# Language: English //# ISBN-10: 0201633981 //# ISBN-13: 978-0201633986

  1. include <iostream>
  2. include <cassert>
  3. include <vector>

using namespace std; template <typename InputIterator, typename T> T accumulate1(InputIterator first, InputIterator last, T init, T (*binary_funct ion)(T x, T y)) // New parameter {

 while (first != last) {
   init = (*binary_function)(init, *first);
   ++first;
 }
 return init;

} int multfun(int x, int y) { return x * y; } int main() {

 int x[5] = {2, 3, 5, 7, 11};
 vector<int> vector1(&x[0], &x[5]);
 int product = accumulate1(vector1.begin(), vector1.end(), 1, &multfun);
 cout << product << endl;
 return 0;

}</source>

2310

Functor

<source lang="cpp">/* The following code example is taken from the book

* "C++ Templates - The Complete Guide"
* by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, 2002
*
* (C) Copyright David Vandevoorde and Nicolai M. Josuttis 2002.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
  1. include <iostream>
  2. include <cmath>
  3. include <cstdlib>

class Abs {

 public:
   // ""function call"":
   double operator() (double v) const {
       return std::abs(v);
   }

}; class Sine {

 public:
   // ""function call"":
   double operator() (double a) const {
       return std::sin(a);
   }

};

template <typename FO1, typename FO2> class Composer {

 private:
   FO1 fo1;  // first/inner function object to call
   FO2 fo2;  // second/outer function object to call
 public:
   // constructor: initialize function objects
   Composer (FO1 f1, FO2 f2)
    : fo1(f1), fo2(f2) {
   }
   // ""function call"": nested call of function objects
   double operator() (double v) {
       return fo2(fo1(v));
   }

};

template<typename FO> void print_values (FO fo) {

   for (int i=-2; i<3; ++i) {
       std::cout << "f(" << i*0.1
                 << ") = " << fo(i*0.1)
                 << "\n";
   }

} int main() {

   // print sin(abs(-0.5))
   std::cout << Composer<Abs,Sine>(Abs(),Sine())(-0.5) << "\n\n";
   // print abs() of some values
   print_values(Abs());
   std::cout << "\n";
   // print sin() of some values
   print_values(Sine());
   std::cout << "\n";
   // print sin(abs()) of some values
   print_values(Composer<Abs, Sine>(Abs(), Sine()));
   std::cout << "\n";
   // print abs(sin()) of some values
   print_values(Composer<Sine, Abs>(Sine(), Abs()));

}</source>

0.479426
f(-0.2) = 0.2
f(-0.1) = 0.1
f(0) = 0
f(0.1) = 0.1
f(0.2) = 0.2
f(-0.2) = -0.198669
f(-0.1) = -0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669

Functor compose 2

<source lang="cpp">/* The following code example is taken from the book

* "C++ Templates - The Complete Guide"
* by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, 2002
*
* (C) Copyright David Vandevoorde and Nicolai M. Josuttis 2002.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
  1. include <iostream>
  2. include <cmath>
  3. include <cstdlib>

class Abs {

 public:
   // ""function call"":
   double operator() (double v) const {
       return std::abs(v);
   }

}; class Sine {

 public:
   // ""function call"":
   double operator() (double a) const {
       return std::sin(a);
   }

};

template <typename FO1, typename FO2> class Composer {

 private:
   FO1 fo1;  // first/inner function object to call
   FO2 fo2;  // second/outer function object to call
 public:
   // constructor: initialize function objects
   Composer (FO1 f1, FO2 f2)
    : fo1(f1), fo2(f2) {
   }
   // ""function call"": nested call of function objects
   double operator() (double v) {
       return fo2(fo1(v));
   }

};

template <typename FO1, typename FO2> inline Composer<FO1,FO2> compose (FO1 f1, FO2 f2) {

   return Composer<FO1,FO2> (f1, f2);

}

template<typename FO> void print_values (FO fo) {

   for (int i=-2; i<3; ++i) {
       std::cout << "f(" << i*0.1
                 << ") = " << fo(i*0.1)
                 << "\n";
   }

} int main() {

   // print sin(abs(-0.5))
   std::cout << compose(Abs(),Sine())(0.5) << "\n\n";
   // print abs() of some values
   print_values(Abs());
   std::cout << "\n";
   // print sin() of some values
   print_values(Sine());
   std::cout << "\n";
   // print sin(abs()) of some values
   print_values(compose(Abs(),Sine()));
   std::cout << "\n";
   // print abs(sin()) of some values
   print_values(compose(Sine(),Abs()));

}</source>

0.479426
f(-0.2) = 0.2
f(-0.1) = 0.1
f(0) = 0
f(0.1) = 0.1
f(0.2) = 0.2
f(-0.2) = -0.198669
f(-0.1) = -0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669

Functor compose 3

<source lang="cpp">/* The following code example is taken from the book

* "C++ Templates - The Complete Guide"
* by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, 2002
*
* (C) Copyright David Vandevoorde and Nicolai M. Josuttis 2002.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
  1. include <iostream>
  2. include <cmath>
  3. include <cstdlib>

class Abs {

 public:
   // ""function call"":
   double operator() (double v) const {
       return std::abs(v);
   }

}; class Sine {

 public:
   // ""function call"":
   double operator() (double a) const {
       return std::sin(a);
   }

}; template <typename C, int N> class BaseMem : public C {

 public:
   BaseMem(C& c) : C(c) { }
   BaseMem(C const& c) : C(c) { }

}; template <typename FO1, typename FO2> class Composer : private BaseMem<FO1,1>,

                private BaseMem<FO2,2> {
 public:
   // constructor: initialize function objects
   Composer(FO1 f1, FO2 f2)
    : BaseMem<FO1,1>(f1), BaseMem<FO2,2>(f2) {
   }
   // ""function call"": nested call of function objects
   double operator() (double v) {
       return BaseMem<FO2,2>::operator()
                (BaseMem<FO1,1>::operator()(v));
   }

}; template <typename FO1, typename FO2> inline Composer<FO1,FO2> compose (FO1 f1, FO2 f2) {

   return Composer<FO1,FO2> (f1, f2);

}

template<typename FO> void print_values (FO fo) {

   for (int i=-2; i<3; ++i) {
       std::cout << "f(" << i*0.1
                 << ") = " << fo(i*0.1)
                 << "\n";
   }

} int main() {

   // print sin(abs(-0.5))
   std::cout << compose(Abs(),Sine())(0.5) << "\n\n";
   // print abs() of some values
   print_values(Abs());
   std::cout << "\n";
   // print sin() of some values
   print_values(Sine());
   std::cout << "\n";
   // print sin(abs()) of some values
   print_values(compose(Abs(),Sine()));
   std::cout << "\n";
   // print abs(sin()) of some values
   print_values(compose(Sine(),Abs()));
   std::cout << "\n";
   // print sin(sin()) of some values
   print_values(compose(Sine(),Sine()));

}</source>

0.479426
f(-0.2) = 0.2
f(-0.1) = 0.1
f(0) = 0
f(0.1) = 0.1
f(0.2) = 0.2
f(-0.2) = -0.198669
f(-0.1) = -0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = 0.198669
f(-0.1) = 0.0998334
f(0) = 0
f(0.1) = 0.0998334
f(0.2) = 0.198669
f(-0.2) = -0.197365
f(-0.1) = -0.0996677
f(0) = 0
f(0.1) = 0.0996677
f(0.2) = 0.197365

Using a function object for operation counting, first version

<source lang="cpp">//Revised from //STL Tutorial and Reference Guide C++ Programming with the Standard Template L ibrary, 2nd Edition //by David R. Musser (Author), Atul Saini (Author) //# Publisher: Addison-Wesley Pub (Sd) (March 1996) //# Language: English //# ISBN-10: 0201633981 //# ISBN-13: 978-0201633986

  1. include <iostream>
  2. include <iomanip>
  3. include <cassert>
  4. include <vector>
  5. include <algorithm>
  6. include <functional>

using namespace std; template <typename T> class less_with_count : public binary_function<T, T, bool> { public:

 less_with_count() { }
 bool operator()(const T& x, const T& y) {
       ++counter;
       return x < y;
 }
 long report() const {return counter;}
 static long counter;

}; template <typename T> long less_with_count<T>::counter = 0; int main() {

 const long N1 = 1000, N2 = 128000;
 for (long N = N1; N <= N2; N *= 2) { 
   vector<int> vector1;
   for (int k = 0; k < N; ++k) 
     vector1.push_back(k);
     
   random_shuffle(vector1.begin(), vector1.end());
   less_with_count<int> comp_counter;
   less_with_count<int>::counter = 0;
   sort(vector1.begin(), vector1.end(), comp_counter);
   cout << comp_counter.report() << endl;
 }
 return 0;

}</source>

11846
26397
56776
125715
271505
596740
1235889
2727581

Using a function object for operation counting, second version

<source lang="cpp">//Revised from //STL Tutorial and Reference Guide C++ Programming with the Standard Template L ibrary, 2nd Edition //by David R. Musser (Author), Atul Saini (Author) //# Publisher: Addison-Wesley Pub (Sd) (March 1996) //# Language: English //# ISBN-10: 0201633981 //# ISBN-13: 978-0201633986

  1. include <iostream>
  2. include <iomanip>
  3. include <cassert>
  4. include <vector>
  5. include <algorithm>
  6. include <functional>

using namespace std; template <typename T> class less_with_count : public binary_function<T, T, bool> { public:

 less_with_count() : counter(0), progenitor(0) { }
 // Copy constructor:
 less_with_count(less_with_count<T>& x) : counter(0), 
     progenitor(x.progenitor ? x.progenitor : &x) { }
 bool operator()(const T& x, const T& y) {
   ++counter;
   return x < y;
 }
 long report() const { return counter; }
 ~less_with_count() {  // Destructor
   if (progenitor) {
     progenitor->counter += counter; 
   }
 }

private:

 long counter;
 less_with_count<T>* progenitor;

}; int main() {

 cout << "Using a function object for operation counting, "
      << "second version." << endl;
 const long N1 = 1000, N2 = 128000;
 for (long N = N1; N <= N2; N *= 2) { 
   vector<int> vector1;
   for (int k = 0; k < N; ++k) 
     vector1.push_back(k);
   random_shuffle(vector1.begin(), vector1.end());
   less_with_count<int> comp_counter;
   sort(vector1.begin(), vector1.end(), comp_counter);
   cout << "Problem size " << setw(9) << N 
        << ",  comparisons performed: " 
        << setw(9) << comp_counter.report() << endl;
 }
 return 0;

}</source>

Using a function object for operation counting, second version.
Problem size      1000,  comparisons performed:     11846
Problem size      2000,  comparisons performed:     26397
Problem size      4000,  comparisons performed:     56776
Problem size      8000,  comparisons performed:    125715
Problem size     16000,  comparisons performed:    271505
Problem size     32000,  comparisons performed:    596740
Problem size     64000,  comparisons performed:   1235889
Problem size    128000,  comparisons performed:   2727581