对多数内建的基本函数对象模板提供了简单的测试
用这种方式如何使用每个模板
并取得相应的操作结果
//: C06:Generators.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Different ways to fill sequences.
#ifndef GENERATORS_H
#define GENERATORS_H
#include <cstring>
#include <set>
#include <cstdlib>
// A generator that can skip over numbers:
class SkipGen {
int i;
int skp;
public:
SkipGen(int start = 0, int skip = 1)
: i(start), skp(skip) {}
int operator()() {
int r = i;
i += skp;
return r;
}
};
// Generate unique random numbers from 0 to mod:
class URandGen {
std::set<int> used;
int limit;
public:
URandGen(int lim) : limit(lim) {}
int operator()() {
while(true) {
int i = int(std::rand()) % limit;
if(used.find(i) == used.end()) {
used.insert(i);
return i;
}
}
}
};
// Produces random characters:
class CharGen {
static const char* source;
static const int len;
public:
char operator()() {
return source[std::rand() % len];
}
};
#endif // GENERATORS_H ///:~
//: C06:Generators.cpp {O}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
#include "Generators.h"
const char* CharGen::source = "ABCDEFGHIJK"
"LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const int CharGen::len = std::strlen(source);
///:~
SkipGen函数对象 返回一个算术序列当前元素的下一个数
共同的差值保存在数据成员skp中CharGen对象返回一个随机的字母表中的字符
//: C06:FunctionObjects.cpp {-bor}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Illustrates selected predefined function object
// templates from the Standard C++ library.
//{L} Generators
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include "Generators.h"
#include "PrintSequence.h"
using namespace std;
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.begin(), r.end(), \
"After " #EXPR);
// For Boolean tests:
#define B(EXPR) EXPR; print(br.begin(), br.end(), \
"After " #EXPR);
// Boolean random generator:
struct BRand {
bool operator()() { return rand() % 2 == 0; }
};
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);
srand(time(0)); // Randomize
generate_n(x.begin(), SZ, urg);
generate_n(y.begin(), SZ, urg);
// Add one to each to guarantee nonzero divide:
transform(y.begin(), y.end(), y.begin(),
bind2nd(plus<int>(), 1));
// Guarantee one pair of elements is ==:
x[0] = y[0];
print(x.begin(), x.end(), "x");
print(y.begin(), y.end(), "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.begin(), b1.end(), "b1");
print(b2.begin(), b2.end(), "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>())));
getchar();
} ///:~
使用了一个简单的函数模板print()
它能够打印任意类型的序列并且可以附加可选择的信息
testUnary()函数有一个源 vector
一个目的vector和一个用在源vector上来产生目的vector的一元函数对象
贴剩下的代码
//: C06:PrintSequence.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Prints the contents of any sequence.
#ifndef PRINTSEQUENCE_H
#define PRINTSEQUENCE_H
#include <algorithm>
#include <iostream>
#include <iterator>
template<typename Iter>
void print(Iter first, Iter last, const char* nm = "",
const char* sep = "\n",
std::ostream& os = std::cout) {
if(nm != 0 && *nm != '\0')
os << nm << ": " << sep;
typedef typename
std::iterator_traits<Iter>::value_type T;
std::copy(first, last,
std::ostream_iterator<T>(std::cout, sep));
os << std::endl;
}
#endif // PRINTSEQUENCE_H ///:~
输出
x:
9
36
34
37
18
44
0
33
20
4
y:
9
28
17
22
5
48
46
34
19
32
After testBinary(x, y, r, plus<int>()):
18
64
51
59
23
92
46
67
39
36
After testBinary(x, y, r, minus<int>()):
0
8
17
15
13
-4
-46
-1
1
-28
After testBinary(x, y, r, multiplies<int>()):
81
1008
578
814
90
2112
0
1122
380
128
After testBinary(x, y, r, divides<int>()):
1
1
2
1
3
0
0
0
1
0
After testBinary(x, y, r, modulus<int>()):
0
8
0
15
3
44
0
33
1
4
After testUnary(x, r, negate<int>()):
-9
-36
-34
-37
-18
-44
0
-33
-20
-4
After testBinary(x, y, br, equal_to<int>()):
1
0
0
0
0
0
0
0
0
0
After testBinary(x, y, br, not_equal_to<int>()):
0
1
1
1
1
1
1
1
1
1
After testBinary(x, y, br, greater<int>()):
0
1
1
1
1
0
0
0
1
0
After testBinary(x, y, br, less<int>()):
0
0
0
0
0
1
1
1
0
1
After testBinary(x, y, br, greater_equal<int>()):
1
1
1
1
1
0
0
0
1
0
After testBinary(x, y, br, less_equal<int>()):
1
0
0
0
0
1
1
1
0
1
After testBinary(x, y, br, not2(greater_equal<int>())):
0
0
0
0
0
1
1
1
0
1
After testBinary(x,y,br,not2(less_equal<int>())):
0
1
1
1
1
0
0
0
1
0
b1:
0
0
1
0
0
0
0
1
0
1
b2:
0
1
1
1
1
1
0
1
1
0
After testBinary(b1, b2, br, logical_and<int>()):
0
0
1
0
0
0
0
1
0
0
After testBinary(b1, b2, br, logical_or<int>()):
0
1
1
1
1
1
0
1
1
1
After testUnary(b1, br, logical_not<int>()):
1
1
0
1
1
1
1
0
1
0
After testUnary(b1, br, not1(logical_not<int>())):
0
0
1
0
0
0
0
1
0
1
T()测试产生数字型值的每一个函数对象
B()测试产生布尔型结果的每一个函数对象
在输出结果中想使布尔型值显示为 真 和 假 而不是 1和0
则要调用cout.set(ios::boolalpha)
一个绑定程序无需产生一元判断函数
它能创建任意的一元函数
//: C06:FBinder.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Binders aren't limited to producing predicates.
//{L} Generators
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
#include "Generators.h"
using namespace std;
int main() {
ostream_iterator<int> out(cout," ");
vector<int> v(15);
srand(time(0)); // Randomize
generate(v.begin(), v.end(), URandGen(20));
copy(v.begin(), v.end(), out);
transform(v.begin(), v.end(), v.begin(),
bind2nd(multiplies<int>(), 10));
copy(v.begin(), v.end(), out);
getchar();
} ///:~
输出 这个还要Generators.h Generators.cpp
2 14 10 7 15 11 4 1 19 0 16 9 13 6 8 20 140 100 70 150 110 40 10 190 0 160 90 130 60 80
因为transform()的第3个参数与第1个参数一样
所以结果元素又被复制回源vector
绑定程序 绑定 的参数不能死一个函数对象
但也无需是一个编译时常量
//: C06:BinderValue.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// The bound argument can vary.
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <cstdlib>
using namespace std;
int boundedRand() { return rand() % 100; }
int main() {
const int SZ = 20;
int a[SZ], b[SZ] = {0};
generate(a, a + SZ, boundedRand);
int val = boundedRand();
int* end = remove_copy_if(a, a + SZ, b,
bind2nd(greater<int>(), val));
// Sort for easier viewing:
sort(a, a + SZ);
sort(b, end);
ostream_iterator<int> out(cout, " ");
cout << "Original Sequence:" << endl;
copy(a, a + SZ, out); cout << endl;
cout << "Values <= " << val << endl;
copy(b, end, out); cout << endl;
getchar();
} ///:~
输出 随机数
Original Sequence:
0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91 95
Values <= 91
0 5 24 27 27 34 36 41 42 45 58 61 62 64 67 69 78 81 91
这里用20个在0到100之间的随机数填充一个数组
当然用户可以在命令行提供一个值
用来限制产生随机数的范围