说是延时求值,注意还是想搞一搞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() << '\n';                          // 5

    auto fn_half = std::bind(my_divide, _1, 2);              // returns x/2
    std::cout << fn_half(10) << '\n';                        // 5

    auto fn_invert = std::bind(my_divide, _2, _1);            // returns y/x
    std::cout << fn_invert(10, 2) << '\n';                    // 0.2

    auto fn_rounding = std::bind<int>(my_divide, _1, _2);   // returns int(x/y)
    std::cout << fn_rounding(10, 3) << '\n';                  // 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) << '\n';           // 20

    // returns ten_two.a
    auto bound_member_data = std::bind(&MyPair::a, ten_two); 
    std::cout << bound_member_data() << '\n';                // 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() << '\n';                          // 5
//
//  auto fn_half = std::bind(my_divide, _1, 2);               // returns x/2
//  std::cout << fn_half(10) << '\n';                        // 5
//
//  auto fn_invert = std::bind(my_divide, _2, _1);            // returns y/x
//  std::cout << fn_invert(10, 2) << '\n';                    // 0.2
//
//  auto fn_rounding = std::bind<int>(my_divide, _1, _2);     // returns int(x/y)
//  std::cout << fn_rounding(10, 3) << '\n';                  // 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) << '\n';           // 20
//
//  auto bound_member_data = std::bind(&MyPair::a, ten_two); // returns ten_two.a
//  std::cout << bound_member_data() << '\n';                // 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