zoukankan      html  css  js  c++  java
  • c++ function和bind

    bind

    定义在头文件 functional 里

    template<typename _Func, typename... _BoundArgs>
    inline typename
    _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type
    bind(_Func&& __f, _BoundArgs&&... __args)
    
    template<typename _Result, typename _Func, typename... _BoundArgs>
    inline
    typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type
    bind(_Func&& __f, _BoundArgs&&... __args)

    函数模板 bind 生成 f 的转发调用包装器。调用此包装器等价于以一些绑定到 args 的参数调用 f 。类似于 python 的 functools.partial

    参数 f 表示可调用对象(函数对象、指向函数指针、函数的引用、指向成员函数指针或指向数据成员指针)

    参数 __args 表示要绑定的参数列表。未绑定参数使用命名空间 std::placeholders 的占位符 _1, _2, _3... 所替换

    需要注意的是:

    调用指向非静态成员函数指针或指向非静态数据成员指针时,首参数必须是引用或指针(可以包含智能指针,如 std::shared_ptr 与 std::unique_ptr),指向将访问其成员的对象。

    到 bind 的参数被复制或移动,而且决不按引用传递,除非包装于 ref 或 cref

    允许同一 bind 表达式中的多重占位符(例如多个 _1 ),但结果仅若对应参数( u1 )是左值或不可移动右值才良好定义。

    #include <random>
    #include <iostream>
    #include <memory>
    #include <functional>
     
    void f(int n1, int n2, int n3, const int& n4, int n5)
    {
        std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '
    ';
    }
     
    int g(int n1)
    {
        return n1;
    }
     
    struct Foo {
        void print_sum(int n1, int n2)
        {
            std::cout << n1+n2 << '
    ';
        }
        int data = 10;
    };
     
    int main()
    {
        using namespace std::placeholders;  // 对于 _1, _2, _3...
     
        // 演示参数重排序和按引用传递
        int n = 7;
        // ( _1 与 _2 来自 std::placeholders ,并表示将来会传递给 f1 的参数)
        auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n);
        n = 10;
        f1(1, 2, 1001); // 1 为 _1 所绑定, 2 为 _2 所绑定,不使用 1001
                        // 进行到 f(2, 1, 42, n, 7) 的调用
     
        // 嵌套 bind 子表达式共享占位符
        auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
        f2(10, 11, 12); // 进行到 f(12, g(12), 12, 4, 5); 的调用
     
        // 常见使用情况:以分布绑定 RNG
        std::default_random_engine e;
        std::uniform_int_distribution<> d(0, 10);
        std::function<int()> rnd = std::bind(d, e); // e 的一个副本存储于 rnd
        for(int n=0; n<10; ++n)
            std::cout << rnd() << ' ';
        std::cout << '
    ';
     
        // 绑定指向成员函数指针
        Foo foo;
        auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
        f3(5);      // 100
     
        // 绑定指向数据成员指针
        auto f4 = std::bind(&Foo::data, _1);
        std::cout << f4(foo) << '
    ';       // 10
     
        // 智能指针亦能用于调用被引用对象的成员
        std::cout << f4(std::make_shared<Foo>(foo)) << '
    ';    // 10
    
        return 0;
    }

    function

    定义在头文件 functional 里

    template<typename _Res, typename... _ArgTypes>
    class function<_Res(_ArgTypes...)>

    类模板 std::function 是通用多态函数封装器。 std::function 的实例能存储、复制及调用任何可回调目标——函数、lambda表达式、bind表达式、其他函数对象,还可以指向成员函数指针和指向数据成员指针。

    存储的可调用对象被称为 std::function 的目标。若 std::function 不含目标,则称它为。调用 std::function 的目标导致抛出 bad_function_call 异常。

    function 满足可复制构造和可复制赋值。

    #include <functional>
    #include <iostream>
     
    struct Foo {
        Foo(int num) : num_(num) {}
        void print_add(int i) const { std::cout << num_+i << '
    '; }
        int num_;
    };
     
    void print_num(int i)
    {
        std::cout << i << '
    ';
    }
     
    struct PrintNum {
        void operator()(int i) const
        {
            std::cout << i << '
    ';
        }
    };
     
    int main()
    {
        // 存储自由函数
        std::function<void(int)> f_display = print_num;
        f_display(-9);      // -9
     
        // 存储 lambda
        std::function<void()> f_display_42 = []() { print_num(42); };
        f_display_42();     // 42
     
        // 存储到 std::bind 调用的结果
        std::function<void()> f_display_31337 = std::bind(print_num, 31337);
        f_display_31337();  // 31337
     
        // 存储到成员函数的调用
        std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
        const Foo foo(314159);
        f_add_display(foo, 1);      // 314160
        f_add_display(314159, 1);   // 314160
     
        // 存储到数据成员访问器的调用
        std::function<int(Foo const&)> f_num = &Foo::num_;
        std::cout << "num_: " << f_num(foo) << '
    ';    // 314159
     
        // 存储到成员函数及对象的调用
        using std::placeholders::_1;
        std::function<void(int)> f_add_display2 = std::bind( &Foo::print_add, foo, _1 );
        f_add_display2(2);      // 314161
     
        // 存储到成员函数和对象指针的调用
        std::function<void(int)> f_add_display3 = std::bind( &Foo::print_add, &foo, _1 );
        f_add_display3(3);      // 314162
     
        // 存储到函数对象的调用
        std::function<void(int)> f_display_obj = PrintNum();
        f_display_obj(18);      // 18
    }
  • 相关阅读:
    Qt QSS美化 基础知识
    Qt QSS教程 QComboBox
    Qt QSS教程 QSpinBox
    Qt QSS教程 QLineEdit
    Qt QSlider qss(round handle) 圆形滑块
    Qt QSS之QSlider滑动条美化
    Qt Creator中使用qss对界面美化没有作用(效果)的问题
    Qt Creator 设置Qss文件文本高亮
    tensorrt中builder.max_workspace_size的作用
    C++宏的一些较复杂的用法,反斜杠,do {}while(0)
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/10215198.html
Copyright © 2011-2022 走看看