下面的代码用gcc version 3.4.5 (mingw-vista special r3)测试
来源于sgi STL的官方手册以及《泛型编程与STL》(Generic Programming and the STL)
// 编译命令行: // g++ test005.cpp // 演示STL迭代器 #include <list> #include <vector> #include <string> #include <iterator> #include <iostream> class Int { public: Int(int x):val(x) { } int get() { return val; } private: int val; }; int main(int argc, const char *argv[]) { { //front_insert_iterator<FrontInsertionSequence>,用于从前面依次插入元素 std::list<int> L; L.push_front(3); std::front_insert_iterator< std::list<int> > ii(L); *ii++ = 0; *ii++ = 1; *ii++ = 2; //输出2 1 0 3 std::copy(L.begin(), L.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } { //back_insert_iterator<BackInsertionSequence>,用于从后面依次插入元素 //效果相当于 //copy(L.begin(), L.end(), back_inserter(v2)); //也相当于更快的方法(如果原来没有元素的话) //vector v1(L.begin(), L.end()); std::list<int> L; L.push_front(3); std::back_insert_iterator< std::list<int> > ii(L); *ii++ = 0; *ii++ = 1; *ii++ = 2; // 输出3 0 1 2 std::copy(L.begin(), L.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } { //insert_iterator<Container>,用于某个位置后面的空挡处插入元素 std::list<int> L; L.push_front(3); std::insert_iterator< std::list<int> > ii(L, L.begin()); *ii++ = 0; *ii++ = 1; *ii++ = 2; std::copy(L.begin(), L.end(), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; } //if(false) { //istream_iterator<T, Distance> / ostream_iterator<T>,用于把输入/输出流转换为迭代器 fflush(stdin); std::vector<int> V; std::cout << "please input some number (. to end)" << std::endl; std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(), std::back_inserter(V)); std::copy(V.begin(), V.end(), std::ostream_iterator<int>(std::cout, "\n")); fflush(stdout); } //if(false) { //istreambuf_iterator / ostreambuf_iterator,用于把输入/输出流缓冲转换为迭代器 fflush(stdin); std::istreambuf_iterator<char> first(std::cin); std::istreambuf_iterator<char> eos; std::cout << "please input string (Ctrl+Z to end)" << std::endl; std::vector<char> buffer(first, eos); std::copy(buffer.begin(), buffer.end(), std::ostreambuf_iterator<char>(std::cout)); std::cout << std::endl; fflush(stdout); } { //reverse_iterator<RandomAccessIterator, T, Reference, Distance>,用于作为参数传入算法时,颠倒容器的前后次序 std::string s = "This is a test."; std::copy(std::reverse_iterator<std::string::iterator>(s.end()), std::reverse_iterator<std::string::iterator>(s.begin()), std::ostream_iterator<char>(std::cout)); std::cout << std::endl; } { //raw_storage_iterator<ForwardIterator, T>,和迭代器类似,但使用已经分配的内存而非用new分配。 //在不分配内存的情况下只调用构造函数,即*r = x等效于construct(&*i, x). int A1[] = {1, 2, 3, 4, 5, 6, 7}; const int N = sizeof(A1) / sizeof(int); Int* A2 = (Int*) malloc(N * sizeof(Int)); std::transform(A1, A1 + N, std::raw_storage_iterator<Int*, int>(A2), std::negate<int>()); for(int i = 0; i < N; i++) { std::cout << "A2[" << i << "] == " << A2[i].get() << std::endl; } std::cout << std::endl; free(A2); } //标准C++允许main不返回,但标准C要求必须返回 return 0; }
// 编译命令行: // g++ test006.cpp // 演示STL函数对象 #include <math.h> #include <assert.h> #include <vector> #include <list> #include <map> #include <iostream> #include <iterator> #include <functional> // for iota / transform #include <ext/numeric> // for hash, or #include <ext/hash_set> #include <ext/hash_map> struct sine:public std::unary_function<double, double> { double operator()(double x) { return sin(x); } }; struct exponentiate : public std::binary_function<double, double, double> { double operator()(double x, double y) { return pow(x, y); } }; struct B { virtual void print() = 0; }; struct D1 : public B { void print() { std::cout << "I'm a D1" << std::endl; } }; struct D2 : public B { void print() { std::cout << "I'm a D2" << std::endl; } }; struct Operation { virtual double eval(double) = 0; }; struct Square : public Operation { double eval(double x) { return x * x; } }; struct Negate : public Operation { double eval(double x) { return -x; } }; int main(int argc, const char *argv[]) { { //unary_function<Arg, Result>,用于作为基类声明一元函数对象(一元仿函数,实际上是个类) //binary_function<Arg1, Arg2, Result>,用于作为基类声明二元函数对象 } { //plus<T> / minus<T> / multiplies<T> / divides<T> / modulus<T>, //序列相加/相减/相乘/相除/取模 //V3 = V1 + V2 const int N = 1000; std::vector<double> V1(N); std::vector<double> V2(N); std::vector<double> V3(N); __gnu_cxx::iota(V1.begin(), V1.end(), 1); std::fill(V2.begin(), V2.end(), 75); assert(V2.size() >= V1.size() && V3.size() >= V1.size()); std::transform(V1.begin(), V1.end(), V2.begin(), V3.begin(), std::plus<double>()); } { //negate<T>,序列取相反数 //V2 = -V1 const int N = 1000; std::vector<int> V1(N); std::vector<int> V2(N); __gnu_cxx::iota(V1.begin(), V1.end(), 1); assert(V2.size() >= V1.size()); std::transform(V1.begin(), V1.end(), V2.begin(), std::negate<int>()); } { //equal_to<T> / not_equal_to<T> / less<T> / greater<T> / less_equal<T> / greater_equal<T> //条件操作,判断是否等于/不等于/小于/大于/小于等于/大于等于某个数 int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0}; const int N = sizeof(A)/sizeof(int); //把0移到最左边的区间 std::partition(A, A + N, std::bind2nd(std::equal_to<int>(), 0)); std::copy(A, A + N, std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl; std::list<int> L(1000); std::fill(L.begin(), L.end(), 75); //查找满足条件的位置 std::list<int>::iterator first_nonzero = std::find_if(L.begin(), L.end(), std::bind2nd(std::not_equal_to<int>(), 0)); assert(first_nonzero == L.end() || *first_nonzero != 0); } { //logical_and<T> / logical_or<T> / logical_not<T> //条件操作,判断两个条件的与/或/非 std::list<int> L; std::fill(L.begin(), L.end(), 75); std::list<int>::iterator in_range = std::find_if(L.begin(), L.end(), __gnu_cxx::compose2(std::logical_and<bool>(), std::bind2nd(std::greater_equal<int>(), 1), std::bind2nd(std::less_equal<int>(), 10))); assert(in_range == L.end() || (*in_range >= 1 && *in_range <= 10)); char str[] = "Hello world!"; const int MAXLEN = sizeof(str) / sizeof(char); const char* wptr = std::find_if(str, str + MAXLEN, __gnu_cxx::compose2(std::logical_or<bool>(), std::bind2nd(std::equal_to<char>(), ' '), std::bind2nd(std::equal_to<char>(), '\n'))); assert(wptr == str + MAXLEN || *wptr == ' ' || *wptr == '\n'); std::vector<bool> V; V.push_back(true); V.push_back(false); std::transform(V.begin(), V.end(), V.begin(), std::logical_not<bool>()); } { //identity<T>,原值返回 int x = 137; __gnu_cxx::identity<int> id; assert(x == id(x)); } { //project1st<Arg1, Arg2>,忽略第二参数 std::vector<int> v1(10, 137); std::vector<char*> v2(10, (char*) 0); std::vector<int> result(10); std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), __gnu_cxx::project1st<int, char*>()); assert(std::equal(v1.begin(), v1.end(), result.begin())); } { //project2nd<Arg1, Arg2>,忽略第一参数 std::vector<char*> v1(10, (char*) 0); std::vector<int> v2(10, 137); std::vector<int> result(10); std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), __gnu_cxx::project2nd<char*, int>()); assert(std::equal(v2.begin(), v2.end(), result.begin())); } { //select1st<Pair>,pair或pair相同接口(如map)的类的第一参数 //select2nd<Pair>,pair或pair相同接口(如map)的类的第二参数 std::map<int, double> M; M[1] = 0.3; M[47] = 0.8; M[33] = 0.1; // 输出1 33 47. std::transform(M.begin(), M.end(), std::ostream_iterator<int>(std::cout, " "), __gnu_cxx::select1st<std::map<int, double>::value_type>()); std::cout << std::endl; // 输出0.3 0.1 0.8 std::transform(M.begin(), M.end(), std::ostream_iterator<double>(std::cout, " "), __gnu_cxx::select2nd<std::map<int, double>::value_type>()); std::cout << std::endl; } { //hash<T>,返回哈希值 __gnu_cxx::hash<const char*> H; std::cout << "foo -> " << H("foo") << std::endl; std::cout << "bar -> " << H("bar") << std::endl; } { //subtractive_rng,伪随机数生成器,减去法 __gnu_cxx::subtractive_rng R; //生成0至4之间的伪随机数 for (int i = 0; i < 20; ++i) std::cout << R(5) << ' '; std::cout << std::endl; } { //mem_fun_t<Result, X>,用于遍历调用多态的虚函数,容器元素是指针 //mem_fun1_t<Result, X, Arg>,传入容器的元素作为参数,遍历调用多态的虚函数,容器元素是指针 //const_mem_fun_t / const_mem_fun1_t,用于const的成员函数,用法类似 std::vector<B*> V; V.push_back(new D1); V.push_back(new D2); V.push_back(new D2); V.push_back(new D1); std::for_each(V.begin(), V.end(), std::mem_fun(&B::print)); std::vector<Operation*> operations; std::vector<double> operands; operations.push_back(new Square); operations.push_back(new Square); operations.push_back(new Negate); operations.push_back(new Negate); operations.push_back(new Square); operands.push_back(1); operands.push_back(2); operands.push_back(3); operands.push_back(4); operands.push_back(5); std::transform(operations.begin(), operations.end(), operands.begin(), std::ostream_iterator<double>(std::cout, "\n"), std::mem_fun(&Operation::eval)); } { //mem_fun_ref_t<Result, X>,用于遍历调用多态的虚函数,容器元素是引用 //mem_fun1_ref_t<Result, X, Arg>,传入容器的元素作为参数,遍历调用多态的虚函数,容器元素是引用 //const_mem_fun_ref_t / const_mem_fun1_ref_t,用于const的成员函数,用法类似 std::vector<D1> V; V.push_back(D1()); V.push_back(D1()); std::for_each(V.begin(), V.end(), std::mem_fun_ref(&B::print)); int A1[5] = {1, 2, 3, 4, 5}; int A2[5] = {1, 1, 2, 3, 5}; int A3[5] = {1, 4, 1, 5, 9}; std::vector<std::vector<int> > V2; V2.push_back(std::vector<int>(A1, A1 + 5)); V2.push_back(std::vector<int>(A2, A2 + 5)); V2.push_back(std::vector<int>(A3, A3 + 5)); int indices[3] = {0, 2, 4}; int& (std::vector<int>::*extract)(std::vector<int>::size_type); //使用&,否则编译器报错 //输出1 2 9 extract = &std::vector<int>::operator[]; std::transform(V2.begin(), V2.end(), indices, std::ostream_iterator<int>(std::cout, "\n"), std::mem_fun_ref(extract)); } { //binder1st<AdaptableBinaryFunction>,用于把第一参数设为常数 std::list<int> L; std::fill(L.begin(), L.end(), 75); std::list<int>::iterator first_nonzero = std::find_if(L.begin(), L.end(), std::bind1st(std::not_equal_to<int>(), 0)); assert(first_nonzero == L.end() || *first_nonzero != 0); } { //binder2nd<AdaptableBinaryFunction>,用于把第二参数设为常数 std::list<int> L; std::fill(L.begin(), L.end(), 75); std::list<int>::iterator first_positive = std::find_if(L.begin(), L.end(), std::bind2nd(std::greater<int>(), 0)); assert(first_positive == L.end() || *first_positive > 0); } { //pointer_to_unary_function<Arg, Result>,用于把一个参数的C函数转为函数对象, //pointer_to_binary_function<Arg1, Arg2, Result>,同上,把两个参数的C函数转为函数对象 //常用于叠加的函数对象如compose1, //如果没有叠加,可以直接使用C函数如fabs,则不需要std::ptr_fun()的辅助 const int N = 1000; std::vector<double> V1(N); __gnu_cxx::iota(V1.begin(), V1.end(), 1); //如果出现错误: //error: expected primary-expression before ',' token //请检查函数对象如std::negate<double>()后面的括号是否遗漏 // //直接使用fabs时不需要使用ptr_fun //std::transform(V1.begin(), V1.end(), V1.begin(), fabs); // std::transform(V1.begin(), V1.end(), V1.begin(), __gnu_cxx::compose1(std::negate<double>(), std::ptr_fun(fabs))); //使用两个参数C函数strcmp进行条件查找 char *str = "OK"; const int N2 = 1000; std::list<char*> L(N2); //使用fill之前需要小心容器的个数(需要在创建时指定,而非缺省) std::fill(L.begin(), L.end(), str); //如果出现这样的错误 //error: missing template arguments before '(' token //提示binder2nd缺少模板参数, //可以输入一个错误的模板参数类型,如<int> //然后看错误提示 assert(!strcmp(L.front(), str)); // //查找第一个等于"OK"的位置 // std::list<char*>::iterator item = std::find_if(L.begin(), L.end(), std::not1( std::binder2nd< std::pointer_to_binary_function<const char*, const char*, int> >( std::ptr_fun(strcmp), "OK"))); assert(!strcmp(*item, "OK")); assert(item == L.end() || strcmp(*item, "OK") == 0); } { //unary_negate<AdaptablePredicate>,用于一元函数逻辑非 //binary_negate<AdaptableBinaryPredicate>,用于二元函数的逻辑非 const int N = 1000; std::list<int> L(N); std::fill(L.begin(), L.end(), 75); std::list<int>::iterator in_range = std::find_if(L.begin(), L.end(), std::not1( __gnu_cxx::compose2(std::logical_and<bool>(), std::bind2nd(std::greater_equal<int>(), 1), std::bind2nd(std::less_equal<int>(), 10)))); assert(in_range == L.end() || !(*in_range >= 1 && *in_range <= 10)); char str[] = "Hello, world!"; const int MAXLEN = sizeof(str) / sizeof(char); const char* wptr = find_if(str, str + MAXLEN, __gnu_cxx::compose2(std::not2(std::logical_or<bool>()), std::bind2nd(std::equal_to<char>(), ' '), std::bind2nd(std::equal_to<char>(), '\n'))); assert(wptr != str + MAXLEN); assert(wptr == str + MAXLEN || !(*wptr == ' ' || *wptr == '\n')); } { //unary_compose<AdaptableUnaryFunction1,AdaptableUnaryFunction2> //用于把两个一元函数f(x),g(x)组合成f(g(x)) //binary_compose<AdaptableBinaryFunction,AdaptableUnaryFunction1,AdaptableUnaryFunction2> //用于把两个二元函数f(x),g(x)组合成f(g(x)) std::vector<double> angles; std::vector<double> sines(100); const double pi = 3.14159265358979323846; for(int i = 0; i <90; i++) { angles.push_back(i); } assert(sines.size() >= angles.size()); std::transform(angles.begin(), angles.end(), sines.begin(), __gnu_cxx::compose1(std::negate<double>(), __gnu_cxx::compose1(std::ptr_fun(sin), std::bind2nd(std::multiplies<double>(), pi / 180.)))); std::list<int> L(100); std::fill(L.begin(), L.end(), 75); std::list<int>::iterator in_range = std::find_if(L.begin(), L.end(), __gnu_cxx::compose2(std::logical_and<bool>(), std::bind2nd(std::greater_equal<int>(), 1), std::bind2nd(std::less_equal<int>(), 10))); assert(in_range == L.end() || (*in_range >= 1 && *in_range <= 10)); std::list<double> L2(100); std::fill(L2.begin(), L2.end(), 75.0); double DBL_MIN = 1.0; //计算sin(x)/(x + DBL_MIN) std::transform(L2.begin(), L2.end(), L2.begin(), __gnu_cxx::compose2(std::divides<double>(), std::ptr_fun(sin), std::bind2nd(std::plus<double>(), DBL_MIN))); } //标准C++允许main不返回,但标准C要求必须返回 return 0; }