C++ Tutorial/Development/Functor
Версия от 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