C++ Tutorial/Development/Functor — различия между версиями

Материал из C\C++ эксперт
Перейти к: навигация, поиск
м (1 версия: Импорт контента...)
 
(нет различий)

Версия 14:21, 25 мая 2010

Demonstrating function pointer passing

//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

#include <iostream>
#include <cassert>
#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;
}
2310

Functor

/* 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.
 */
#include <iostream>
#include <cmath>
#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()));
}
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

/* 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.
 */
#include <iostream>
#include <cmath>
#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()));
}
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

/* 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.
 */
#include <iostream>
#include <cmath>
#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()));
}
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

//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

#include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#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;
}
11846
26397
56776
125715
271505
596740
1235889
2727581

Using a function object for operation counting, second version

//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
#include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#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;
}
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