天天看点

C++11>仿函数 std::function、std::bind

std::function,通用多态的函数封装器,是一个函数模板类

std::bind,函数的转发调用包装器,是一个函数模板

CSDN-那事那人,简书-geore…

⚫️ s t d : : f u n c t i o n \color{green}{std::function} std::function

储存函数或函数调用,更好的封装代码,方便调用

#include <functional>
#include <iostream>

struct Foo {
	Foo(int num) : num_(num) {}
	void print_add(int i) const { std::cout << num_ + i << '\n'; }
	int num_;
};

void print_num(int i)
{
	std::cout << i << '\n';
}

struct PrintNum {
	void operator()(int i) const
	{
		std::cout << i << '\n';
	}
};

int main()
{
	// 存储自由函数
	std::function<void(int)> f_display = print_num;
	f_display(-9);

	// 存储 lambda
	std::function<void()> f_display_42 = []() { print_num(42); };
	f_display_42();

	// 存储到 std::bind 调用的结果
	std::function<void()> f_display_31337 = std::bind(print_num, 31337);
	f_display_31337();

	// 存储到成员函数的调用
	std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
	const Foo foo(314159);
	f_add_display(foo, 1);
	f_add_display(314159, 1);

	// 存储到数据成员访问器的调用
	std::function<int(Foo const&)> f_num = &Foo::num_;
	std::cout << "num_: " << f_num(foo) << '\n';

	// 存储到成员函数及对象的调用
	using std::placeholders::_1;
	std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
	f_add_display2(2);

	// 存储到成员函数和对象指针的调用
	std::function<void(int)> f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
	f_add_display3(3);

	// 存储到函数对象的调用
	std::function<void(int)> f_display_obj = PrintNum();
	f_display_obj(18);

	std::system("pause");
}
           

⚫️ s t d : : b i n d \color{green}{std::bind} std::bind

注意使用bind对象时的传参,_1是和第一个参数绑定的,_3是和第三个参数绑定的

#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 << '\n';
}
 
int g(int n1)
{
    return n1;
}
 
struct Foo {
    void print_sum(int n1, int n2)
    {
        std::cout << n1+n2 << '\n';
    }
    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, 42, _1, std::cref(n), n);
    n = 10;
    f1(1, 2, 1001); // 1 为 _1 所绑定, 2 为 _2 所绑定,不使用 1001
                    // 进行到 f(2, 42, 1, 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 << '\n';
 
    // 绑定指向成员函数指针
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5);
 
    // 绑定指向数据成员指针
    auto f4 = std::bind(&Foo::data, _1);
    std::cout << f4(foo) << '\n';
 
    // 智能指针亦能用于调用被引用对象的成员
    std::cout << f4(std::make_shared<Foo>(foo)) << '\n'
              << f4(std::make_unique<Foo>(foo)) << '\n';

	std::system("pause");
}
           

继续阅读