【C++标准库】STL函数对象及Lambda
函数对象function object,又称仿函数functors,是定义了operator()的对象。
class FunctionObjectType { public: void operator() () { //statement } }
1 /* The following code example is taken from the book 2 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition" 3 * by Nicolai M. Josuttis, Addison-Wesley, 2012 4 * 5 * (C) Copyright Nicolai M. Josuttis 2012. 6 * Permission to copy, use, modify, sell and distribute this software 7 * is granted provided this copyright notice appears in all copies. 8 * This software is provided "as is" without express or implied 9 * warranty, and with no claim as to its suitability for any purpose. 10 */ 11 #include <iostream> 12 #include <string> 13 #include <deque> 14 #include <set> 15 #include <algorithm> 16 using namespace std; 17 18 19 /* class Person 20 */ 21 class Person { 22 private: 23 string fn; // first name 24 string ln; // last name 25 public: 26 Person() { 27 } 28 Person(const string& f, const string& n) 29 : fn(f), ln(n) { 30 } 31 string firstname() const; 32 string lastname() const; 33 // ... 34 }; 35 36 inline string Person::firstname() const { 37 return fn; 38 } 39 40 inline string Person::lastname() const { 41 return ln; 42 } 43 44 ostream& operator<< (ostream& s, const Person& p) 45 { 46 s << "[" << p.firstname() << " " << p.lastname() << "]"; 47 return s; 48 } 49 50 51 /* class for function predicate 52 * - operator () returns whether a person is less than another person 53 */ 54 class PersonSortCriterion { 55 public: 56 bool operator() (const Person& p1, const Person& p2) const { 57 /* a person is less than another person 58 * - if the last name is less 59 * - if the last name is equal and the first name is less 60 */ 61 return p1.lastname()<p2.lastname() || 62 (p1.lastname() == p2.lastname() && 63 p1.firstname()<p2.firstname()); 64 } 65 }; 66 67 68 int main() 69 { 70 Person p1("nicolai", "josuttis"); 71 Person p2("ulli", "josuttis"); 72 Person p3("anica", "josuttis"); 73 Person p4("lucas", "josuttis"); 74 Person p5("lucas", "otto"); 75 Person p6("lucas", "arm"); 76 Person p7("anica", "holle"); 77 78 // declare set type with special sorting criterion 79 typedef set<Person, PersonSortCriterion> PersonSet; 80 81 // create such a collection 82 PersonSet coll; 83 coll.insert(p1); 84 coll.insert(p2); 85 coll.insert(p3); 86 coll.insert(p4); 87 coll.insert(p5); 88 coll.insert(p6); 89 coll.insert(p7); 90 91 // do something with the elements 92 // - in this case: output them 93 cout << "set:" << endl; 94 PersonSet::iterator pos; 95 for (pos = coll.begin(); pos != coll.end(); ++pos) { 96 cout << *pos << endl; 97 } 98 }
for_each获取function object的状态
#include <iostream> #include <vector> #include <algorithm> using namespace std; class MeanValue { private: long num; //num of elements long sum; //sum of values public: MeanValue():num(0),sum(0) { } void operator() (int elem) { ++num; sum += elem; } double value() { return static_cast<double>(sum) / static_cast<double>(num); } }; int main() { vector<int> coll = { 1,2,3,4,5,6,7,8 }; MeanValue mv = for_each(coll.begin(), coll.end(), MeanValue()); cout << "mean value:" << mv.value() << endl; return 0; }
预定义的function object
C++标准库提供了许多预定义的function object和binder,后者允许你合成更多精巧的function object。使用时需包含头文件<functional>
bind()函数对象适配器
1 #include <iostream> 2 #include <functional> 3 using namespace std; 4 using namespace std::placeholders; //定义占位符 5 6 int main() 7 { 8 auto plus10 = bind(plus<int>(), _1, 10); //以占位符_1表示第一个参数,以10为第二个参数 9 cout << "+10: " << plus10(7) << endl; //17 10 11 auto plus10times2 = bind(multiplies<int>(), 12 bind(plus<int>(), 13 _1, 10), 14 2); 15 cout << "+10*2: " << plus10times2(7) << endl; //34 16 17 auto pow3 = bind(multiplies<int>(),bind(multiplies<int>(),_1, _1),_1); 18 cout << "x*x*x: " << pow3(7) << endl; 19 20 auto inversDivide = bind(divides<double>(), _2, _1); 21 cout << "invdiv: " << inversDivide(49, 7) << endl; // 1/7 22 return 0; 23 }
运用Lambda
Lambda提供了一种直观、易读的方式,可将独特的行为传递给算法和容器的成员函数。
Lambda表达式完整声明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
其中:
- capture list:捕获外部变量列表
- params list:形参列表
- mutable指示符:用来说用是否可以修改捕获的变量
- exception:异常设定
- return type:返回类型
- function body:函数体
Lambda调用全局函数
1 /* The following code example is taken from the book 2 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition" 3 * by Nicolai M. Josuttis, Addison-Wesley, 2012 4 * 5 * (C) Copyright Nicolai M. Josuttis 2012. 6 * Permission to copy, use, modify, sell and distribute this software 7 * is granted provided this copyright notice appears in all copies. 8 * This software is provided "as is" without express or implied 9 * warranty, and with no claim as to its suitability for any purpose. 10 */ 11 #include <iostream> 12 #include <algorithm> 13 #include <locale> 14 #include <string> 15 using namespace std; 16 17 char myToupper(char c) 18 { 19 std::locale loc; 20 return std::use_facet<std::ctype<char> >(loc).toupper(c); 21 } 22 23 int main() 24 { 25 string s("Internationalization"); 26 string sub("Nation"); 27 28 // search substring case insensitive 29 string::iterator pos; 30 pos = search(s.begin(), s.end(), // string to search in 31 sub.begin(), sub.end(), // substring to search 32 [](char c1, char c2) { // compar. criterion 33 return myToupper(c1) == myToupper(c2); 34 }); 35 if (pos != s.end()) { 36 cout << "\"" << sub << "\" is part of \"" << s << "\"" 37 << endl; 38 } 39 }
Lambda调用成员函数
1 /* The following code example is taken from the book 2 * "The C++ Standard Library - A Tutorial and Reference, 2nd Edition" 3 * by Nicolai M. Josuttis, Addison-Wesley, 2012 4 * 5 * (C) Copyright Nicolai M. Josuttis 2012. 6 * Permission to copy, use, modify, sell and distribute this software 7 * is granted provided this copyright notice appears in all copies. 8 * This software is provided "as is" without express or implied 9 * warranty, and with no claim as to its suitability for any purpose. 10 */ 11 #include <functional> 12 #include <algorithm> 13 #include <vector> 14 #include <iostream> 15 #include <string> 16 using namespace std; 17 using namespace std::placeholders; 18 19 class Person { 20 private: 21 string name; 22 public: 23 Person(const string& n) : name(n) { 24 } 25 void print() const { 26 cout << name << endl; 27 } 28 void print2(const string& prefix) const { 29 cout << prefix << name << endl; 30 } 31 //... 32 }; 33 34 int main() 35 { 36 vector<Person> coll 37 = { Person("Tick"), Person("Trick"), Person("Track") }; 38 39 // call member function print() for each person 40 for_each(coll.begin(), coll.end(), 41 [](const Person& p) { 42 p.print(); 43 }); 44 cout << endl; 45 46 // call member function print2() with additional argument for each person 47 for_each(coll.begin(), coll.end(), 48 [](const Person& p) { 49 p.print2("Person: "); 50 }); 51 }