【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 }
View Code

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;
}
View Code

 预定义的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 }
View Code

 运用Lambda

Lambda提供了一种直观、易读的方式,可将独特的行为传递给算法和容器的成员函数。

Lambda表达式完整声明格式如下:

[capture list] (params list) mutable exception-> return type { function body }

其中:

  1. capture list:捕获外部变量列表
  2. params list:形参列表
  3. mutable指示符:用来说用是否可以修改捕获的变量
  4. exception:异常设定
  5. return type:返回类型
  6. 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 }
View Code

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 }
View Code

 

posted @ 2018-08-18 10:14  summer91  阅读(1026)  评论(0编辑  收藏  举报