Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
B.Eckel - Thinking in C++, Vol.2, 2nd edition.pdf
Скачиваний:
50
Добавлен:
08.05.2013
Размер:
2.09 Mб
Скачать

as function objects). The classification of function objects in the STL is based on whether the operator( ) takes zero, one or two arguments, and if it returns a bool or non-bool value.

Generator: Takes no arguments, and returns a value of the desired type. A

RandomNumberGenerator is a special case.

UnaryFunction: Takes a single argument of any type and returns a value which may be of a different type.

BinaryFunction: Takes two arguments of any two types and returns a value of any type.

A special case of the unary and binary functions is the predicate, which simply means a function that returns a bool. A predicate is a function you use to make a true/false decision.

Predicate: This can also be called a UnaryPredicate. It takes a single argument of any type and returns a bool.

BinaryPredicate: Takes two arguments of any two types and returns a bool.

StrictWeakOrdering: A binary predicate that says that if you have two objects and neither one is less than the other, they can be regarded as equivalent to each other.

In addition, there are sometimes qualifications on object types that are passed to an algorithm. These qualifications are given in the template argument type identifier name:

LessThanComparable: A class that has a less-than operator<.

Assignable: A class that has an assignment operator= for its own type. EqualityComparable: A class that has an equivalence operator== for its own type.

Automatic creation of function objects

The STL has, in the header file <functional>, a set of templates that will automatically create function objects for you. These generated function objects are admittedly simple, but the goal is to provide very basic functionality that will allow you to compose more complicated function objects, and in many situations this is all you’ll need. Also, you’ll see that there are some function object adapters that allow you to take the simple function objects and make them slightly more complicated.

Here are the templates that generate function objects, along with the expressions that they effect.

Name

Type

Result produced by generated function

 

 

object

 

 

 

plus

BinaryFunction

arg1 + arg2

 

 

 

minus

BinaryFunction

arg1 - arg2

 

 

 

multiplies

BinaryFunction

arg1 * arg2

 

 

 

Chapter 15: Multiple Inheritance

265

Name

Type

Result produced by generated function

 

 

object

 

 

 

divides

BinaryFunction

arg1 / arg2

 

 

 

modulus

BinaryFunction

arg1 % arg2

 

 

 

negate

UnaryFunction

- arg1

 

 

 

equal_to

BinaryPredicate

arg1 == arg2

 

 

 

not_equal_to

BinaryPredicate

arg1 != arg2

 

 

 

greater

BinaryPredicate

arg1 > arg2

 

 

 

less

BinaryPredicate

arg1 < arg2

 

 

 

greater_equal

BinaryPredicate

arg1 >= arg2

 

 

 

less_equal

BinaryPredicate

arg1 <= arg2

 

 

 

logical_and

BinaryPredicate

arg1 && arg2

 

 

 

logical_or

BinaryPredicate

arg1 || arg2

 

 

 

logical_not

UnaryPredicate

!arg1

 

 

 

not1( )

Unary Logical

!(UnaryPredicate(arg1))

 

 

 

not2( )

Binary Logical

!(BinaryPredicate(arg1, arg2))

 

 

 

The following example provides simple tests for each of the built-in basic function object templates. This way, you can see how to use each one, along with their resulting behavior.

//: C05:FunctionObjects.cpp

//Using the predefined function object templates

//in the Standard C++ library

//This will be defined shortly:

#include "Generators.h" #include <algorithm> #include <vector> #include <iostream> #include <functional> using namespace std;

template<typename T>

void print(vector<T>& v, char* msg = "") { if(*msg != 0)

cout << msg << ":" << endl;

Chapter 15: Multiple Inheritance

266

copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));

cout << endl;

}

template<typename Contain, typename UnaryFunc> void testUnary(Contain& source, Contain& dest,

UnaryFunc f) { transform(source.begin(), source.end(),

dest.begin(), f);

}

template<typename Contain1, typename Contain2, typename BinaryFunc>

void testBinary(Contain1& src1, Contain1& src2, Contain2& dest, BinaryFunc f) { transform(src1.begin(), src1.end(),

src2.begin(), dest.begin(), f);

}

//Executes the expression, then stringizes the

//expression into the print statement:

#define T(EXPR) EXPR; print(r, "After " #EXPR); // For Boolean tests:

#define B(EXPR) EXPR; print(br,"After " #EXPR);

// Boolean random generator: struct BRand {

BRand() { srand(time(0)); } bool operator()() {

return rand() > RAND_MAX / 2;

}

};

int main() {

const int sz = 10; const int max = 50;

vector<int> x(sz), y(sz), r(sz);

//An integer random number generator: URandGen urg(max); generate_n(x.begin(), sz, urg); generate_n(y.begin(), sz, urg);

//Add one to each to guarantee nonzero divide:

Chapter 15: Multiple Inheritance

267

transform(y.begin(), y.end(), y.begin(), bind2nd(plus<int>(), 1));

//Guarantee one pair of elements is ==: x[0] = y[0];

print(x, "x"); print(y, "y");

//Operate on each element pair of x & y,

//putting the result into r: T(testBinary(x, y, r, plus<int>())); T(testBinary(x, y, r, minus<int>())); T(testBinary(x, y, r, multiplies<int>())); T(testBinary(x, y, r, divides<int>())); T(testBinary(x, y, r, modulus<int>())); T(testUnary(x, r, negate<int>())); vector<bool> br(sz); // For Boolean results B(testBinary(x, y, br, equal_to<int>()));

B(testBinary(x, y, br, not_equal_to<int>())); B(testBinary(x, y, br, greater<int>())); B(testBinary(x, y, br, less<int>())); B(testBinary(x, y, br, greater_equal<int>())); B(testBinary(x, y, br, less_equal<int>())); B(testBinary(x, y, br,

not2(greater_equal<int>()))); B(testBinary(x,y,br,not2(less_equal<int>()))); vector<bool> b1(sz), b2(sz); generate_n(b1.begin(), sz, BRand()); generate_n(b2.begin(), sz, BRand());

print(b1, "b1"); print(b2, "b2");

B(testBinary(b1, b2, br, logical_and<int>())); B(testBinary(b1, b2, br, logical_or<int>())); B(testUnary(b1, br, logical_not<int>())); B(testUnary(b1, br, not1(logical_not<int>())));

}///:~

To keep this example small, some tools are created. The print( ) template is designed to print any vector<T>, along with an optional message. Since print( ) uses the STL copy( ) algorithm to send objects to cout via an ostream_iterator, the ostream_iterator must know the type of object it is printing, and therefore the print( ) template must know this type also. However, you’ll see in main( ) that the compiler can deduce the type of T when you hand it a vector<T>, so you don’t have to hand it the template argument explicitly; you just say print(x) to print the vector<T> x.

Chapter 15: Multiple Inheritance

268

Соседние файлы в предмете Численные методы
  • #
    08.05.20133.99 Mб22A.Menezes, P.van Oorschot,S.Vanstone - HANDBOOK OF APPLIED CRYPTOGRAPHY.djvu
  • #
  • #
    08.05.20135.91 Mб24B.Eckel - Thinking in Java, 3rd edition (beta).pdf
  • #
  • #
    08.05.20136.09 Mб17D.MacKay - Information Theory, Inference, and Learning Algorithms.djvu
  • #
    08.05.20133.85 Mб15DIGITAL Visual Fortran ver.5.0 - Programmers Guide to Fortran.djvu
  • #
    08.05.20131.84 Mб12E.A.Lee, P.Varaiya - Structure and Interpretation of Signals and Systems.djvu