zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    JavaScript和Applet通信
    HashTable和HashMap的区别
    JAVA中有关byte,int,long这些基本数据类型的存储方式以及负数在JAVA中的表示方式
    浏览带有最新JAVA技术的Applet
    JAVA byte[], int, long三者之间的相互转换代码
    使用正则表达式将JSP中文本标签抽取出来填到PropertyFile中
    JAVA多线程-继承Thread类和实现Runnable接口的区别
    Java Conditional Compile Java条件编译
    Alexa 网站排名
    AJAX 教程
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7073561.html
Copyright © 2011-2022 走看看