• 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
  • 相关阅读:
    利用Event和MapFile进程共享信息
    基于不可靠数据报的文件传输
    Simple .NET code and memory profiler
    一步一步Asp.Net MVC系列_权限管理之权限控制
    新的起点,新的开始
    找工作的你需要了解和准备的东西
    我的大学读书生涯
    一步一步Asp.Net MVC系列_权限管理数据库与ViewModel篇
    一步一步asp.net_日志导航
    一步一步Asp.Net MVC系列_权限管理总结(附MVC权限管理系统源码)
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7073561.html
Copyright © 2020-2023  润新知