1. 程式人生 > >C++11新特性應用--實現延時求值(std::function和std::bind)

C++11新特性應用--實現延時求值(std::function和std::bind)

說是延時求值,注意還是想搞一搞std::function和std::bind。

現在就算是補充吧,再把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