• C++11新特性应用--实现延时求值(std::function和std::bind)


    说是延时求值,注意还是想搞一搞std::function和std::bind。

    之前博客《C++11新特性之std::function》注意是std::function怎样实现回调函数。

    如今就算是补充吧,再把std::bind进行讨论讨论。

    何为Callable Objects?
    就可以调用对象,比方函数指针、仿函数、类成员函数指针等都可称为可调用对象。

    对象包装器
    Function wrapper
    Class that can wrap any kind of callable element (such as functions and function objects) into a copyable object, and whose type depends solely on its call signature (and not on the callable element type itself).

    An object of a function class instantiation can wrap any of the following kinds of callable objects: a function, a function pointer, a pointer to member, or any kind of function object (i.e., an object whose class defines operator(), including closures).

    A decay copy of the wrapped callable object is stored internally by the object, which becomes the function’s target. The specific type of this target callable object is not needed in order to instantiate the function wrapper class; only its call signature.

    以下用一段代码:

    #include<iostream>
    #include<functional>
    
    //普通函数
    void func(void)
    {
        std::cout << "1" << std::endl;
    }
    
    //类的成员函数
    class A
    {
    public:
        static int A_func(int a)
        {
            std::cout << "2" << "(" << a << ")" << std::endl;
            return a;
        }
    };
    
    //仿函数
    class B
    {
    public:
        int operator()(int a)
        {
            std::cout << "2" << "(" << a << ")" << std::endl;
            return a;
        }
    };
    
    int main()
    {
        std::function<void(void)> fun1 = func;
        fun1();
    
        std::function<int(int)> fun2 = A::A_func;
        std::cout << fun2(123) << std::endl;
    
        B b;
        fun2 = b;
        std::cout << fun2(123) << std::endl;
    
        return 0;
    }
    //输出:
    1
    2(123)
    123
    2(123)
    123

    接下来std::function用于回调就不浪费篇幅了,接下来注意分析std::bind。

    何为std::bind?
    字面意思。绑定器。
    simple
    template

    #include <iostream>     // std::cout
    #include <functional>   // std::bind
    
    // a function: (also works with function object: std::divides<double> my_divide;)
    double my_divide(double x, double y) { return x / y; }
    
    struct MyPair {
        double a, b;
        double multiply() { return a*b; }
    };
    
    int main() {
        using namespace std::placeholders;    // adds visibility of _1, _2, _3,...
    
        // binding functions:
        auto fn_five = std::bind(my_divide, 10, 2);              // returns 10/2
        std::cout << fn_five() << '
    ';                          // 5
    
        auto fn_half = std::bind(my_divide, _1, 2);              // returns x/2
        std::cout << fn_half(10) << '
    ';                        // 5
    
        auto fn_invert = std::bind(my_divide, _2, _1);            // returns y/x
        std::cout << fn_invert(10, 2) << '
    ';                    // 0.2
    
        auto fn_rounding = std::bind<int>(my_divide, _1, _2);   // returns int(x/y)
        std::cout << fn_rounding(10, 3) << '
    ';                  // 3
    
        MyPair ten_two{ 10,2 };
    
        // binding members:
    
        // returns x.multiply()
        auto bound_member_fn = std::bind(&MyPair::multiply, _1);               
    
        std::cout << bound_member_fn(ten_two) << '
    ';           // 20
    
        // returns ten_two.a
        auto bound_member_data = std::bind(&MyPair::a, ten_two); 
        std::cout << bound_member_data() << '
    ';                // 10
    
        return 0;
    }

    _ 1中的 _ 表示的是占位符,由using namespace std::placeholders; 提供。详细的话找机会再研究。

    主要看看上面的代码。bind的几种使用方式。
    能够看到。能够绑定所有參数,也能够绑定部分參数。

    你可能已经感到bind的威力了吧,那不是重点。与function的结合才是重要的:

    //#include <iostream>     // std::cout
    //#include <functional>   // std::bind
    //
    //// a function: (also works with function object: std::divides<double> my_divide;)
    //double my_divide(double x, double y) { return x / y; }
    //
    //struct MyPair {
    //  double a, b;
    //  double multiply() { return a*b; }
    //};
    //
    //int main() {
    //  using namespace std::placeholders;    // adds visibility of _1, _2, _3,...
    //
    //                                        // binding functions:
    //  auto fn_five = std::bind(my_divide, 10, 2);               // returns 10/2
    //  std::cout << fn_five() << '
    ';                          // 5
    //
    //  auto fn_half = std::bind(my_divide, _1, 2);               // returns x/2
    //  std::cout << fn_half(10) << '
    ';                        // 5
    //
    //  auto fn_invert = std::bind(my_divide, _2, _1);            // returns y/x
    //  std::cout << fn_invert(10, 2) << '
    ';                    // 0.2
    //
    //  auto fn_rounding = std::bind<int>(my_divide, _1, _2);     // returns int(x/y)
    //  std::cout << fn_rounding(10, 3) << '
    ';                  // 3
    //
    //  MyPair ten_two{ 10,2 };
    //
    //  // binding members:
    //  auto bound_member_fn = std::bind(&MyPair::multiply, _1); // returns x.multiply()
    //  std::cout << bound_member_fn(ten_two) << '
    ';           // 20
    //
    //  auto bound_member_data = std::bind(&MyPair::a, ten_two); // returns ten_two.a
    //  std::cout << bound_member_data() << '
    ';                // 10
    //
    //  return 0;
    //}
    
    #include<iostream>
    #include<functional>
    
    class A {
    public:
        int i_ = 0;
        void output(int x, int y)
        {
            std::cout << x << " " << y << std::endl;
        }
    };
    
    int main()
    {
        A a;
        std::function<void(int, int)> func1 = std::bind(&A::output, &a, std::placeholders::_1,
            std::placeholders::_2);
        func1(1, 2);
    
        std::function<int&(void)> func2 = std::bind(&A::i_, &a);
        func2() = 888;
    
        std::cout << a.i_ << std::endl;
        return 0;
    }
    
    //输出:
    1 2
    888
  • 相关阅读:
    DRUPAL 关于 $user 用户权限
    Delphi中代替WebBrowser控件的第三方控件
    最新美行地图Z13升级攻略
    Drupal Form问题汇总
    美行四维图新导航地图可以升级了!!
    Redis 主从配置
    MariaDB 双主复制的配置
    MariaDB 主从复制的配置
    在CentOS下利用Python+selenium获取腾讯首页的今日话题。
    利用Simple-RTMP-Server(SRS)来进行直播
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7073561.html
Copyright © 2020-2023  润新知