C++11 std::bind std::function 高级使用方法[通俗易懂]

C++11 std::bind std::function 高级使用方法

大家好,又见面了,我是全栈君。

从最基础的了解,std::bind和std::function

/* 
 * File:   main.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 */
#include <iostream>
#include <functional>
#include <typeinfo>
#include <string.h>

int add1(int i, int j, int k) {
    return i + j + k;
}


class Utils {
public:
    Utils(const char* name) {
        strcpy(_name, name);
    }
    
    void sayHello(const char* name) const {
        std::cout << _name << " say: hello " << name << std::endl;
    }
    
    static int getId() {
        return 10001;
    } 
    
    int operator()(int i, int j, int k) const {
        return i + j + k;
    }
    
private:
    char _name[32];
};


/*
 * 
 */
int main(void) {
    
    // 绑定全局函数
    auto add2 = std::bind(add1, std::placeholders::_1, std::placeholders::_2, 10);
    // 函数add2 = 绑定add1函数。參数1不变,參数2不变。參数3固定为10.
    std::cout << typeid(add2).name() << std::endl;
    std::cout << "add2(1,2) = " << add2(1, 2) << std::endl;
    
    std::cout << "\n---------------------------" << std::endl;
    
    // 绑定成员函数
    Utils utils("Vicky");
    auto sayHello = std::bind(&Utils::sayHello, utils/*调用者*/, std::placeholders::_1/*參数1*/);
    sayHello("Jack");
    
    auto sayHelloToLucy = std::bind(&Utils::sayHello, utils/*调用者*/, "Lucy"/*固定參数1*/);
    sayHelloToLucy();
    
    // 绑定静态成员函数
    auto getId = std::bind(&Utils::getId);
    std::cout << getId() << std::endl;
    
    std::cout << "\n---------------------------" << std::endl;
    
    // 绑定operator函数
    auto add100 = std::bind(&Utils::operator (), utils, std::placeholders::_1, std::placeholders::_2, 100);
    std::cout << "add100(1, 2) = " << add100(1, 2) << std::endl;
    
    // 注意:无法使用std::bind()绑定一个重载函数
    
    return 0;
}

/* 
 * File:   main2.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 */
#include <iostream>
#include <typeinfo>


void sayHello() {
    std::cout << "Hello world !" << std::endl;
}

int sum(int i, int j, int k) {
    return i + j + k;
}

template <typename T>
class Func {
public:

    Func(T fun) {
        if (!fun) {
            throw "fun nullptr";
        }
        _fun = fun;
    }

    template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
    R Call(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
        return _fun(a1, a2, a3, a4, a5);
    }

    template<typename R, typename A1, typename A2, typename A3, typename A4>
    R Call(A1 a1, A2 a2, A3 a3, A4 a4) {
        return _fun(a1, a2, a3, a4);
    }

    template<typename R, typename A1, typename A2, typename A3>
    R Call(A1 a1, A2 a2, A3 a3) {
        return _fun(a1, a2, a3);
    }

    template<typename R, typename A1, typename A2>
    R Call(A1 a1, A2 a2) {
        return _fun(a1, a2);
    }

    template<typename R, typename A1>
    R Call(A1 a1) {
        return _fun(a1);
    }

    template<typename R>
    R Call() {
        return _fun();
    }

    void Call() {
        _fun();
    }

private:
    T _fun;
};

#include <functional>

template<typename R = void, typename... Args>
class Fn {
public:
    Fn(std::function<R(Args...)> fun) : _fun(fun) {
    }
    
    R operator()(Args... args) {
        return _fun(args...);
    }
private:
    std::function<R(Args...) > _fun;
};

/*
 * 将函数注冊到对象中。通过对象直接调用
 */
int main(void) {


    Func<void(*)() > sayHelloFunc(sayHello);
    sayHelloFunc.Call();


    Func<int (*)(int, int, int) > sumFunc(sum);
    std::cout << "sumFunc.Call<int>(1, 2, 3) : " << sumFunc.Call<int>(1, 2, 3) << std::endl;


    std::cout << "\n---------------------------" << std::endl;

    Fn<> sayHelloFn(sayHello);
    sayHelloFn();
    
    Fn<int, int, int, int> sumFn(sum);
    std::cout << "sumFn(1, 2, 3) : " << sumFn(1, 2, 3) << std::endl;

    std::cout << "\n---------------------------" << std::endl;

    return 0;
}

Hello world !
sumFunc.Call<int>(1, 2, 3) : 6

—————————
Hello world !
sumFn(1, 2, 3) : 6

—————————

上面的样例很有趣,使用了2种方案。将一个函数,注冊到一个对象/仿函数中,而且通过一个对象/仿函数来直接调用调用。
样例显而易见的。第2种方案更佳简洁,而且对传递參数有明白的推断,当參数类型或数量不对的时候,编译器将导致失败。
这样的方案,能够将类的成员变量直接作为函数的參数使用,或者,如我:
http://blog.csdn.net/eclipser1987/article/details/23926395
这篇文章中,无法直接调用脚本函数类。有了好的解决的方法。这个我将随后补充。

#include <list>
#include <functional>

template<typename... Args>
class Fns
{
private:

	std::list<std::function<void(Args...)> > _calls;

public:

	virtual ~Fns()
	{
		_calls.clear();
	}

	void connect(std::function<void(Args...)> fct)
	{
		_calls.push_back(fct);
	}

	template<typename Object>
	void connect(Object* object, void (Object::*method)(Args...))
	{
		_calls.push_back([object,method](Args... args){(*object.*method)(args...);});
	}

	template<typename Object>
	void connect(Object* object, void (Object::*method)(Args...) const)
	{
		_calls.push_back([object,method](Args... args){(*object.*method)(args...);});
	}

	template<typename Object>
	void connect(const Object* object, void (Object::*method)(Args...) const)
	{
		_calls.push_back([object,method](Args... args){(*object.*method)(args...);});
	}

	void emit(Args... args)
	{
		for(auto call : _calls)
			call(args...);
	}
};

#include <cstdio>
#include "Signal.hpp"

class Foo
{
public:

	void bar(int x, int y)
	{
		printf("Foo::bar(%d, %d)\n", x, y);
	}
};

void foobar(int x, int y)
{
	printf("foobar(%d, %d)\n", x, y);
}

int main(void)
{
	Foo foo;
	Fns<int, int> s;

	// Connect a function
	s.connect(foobar);
	// Connect a class method
	s.connect(&foo, &Foo::bar);
	// Create and connect some lambda expression
	s.connect([&foo](int x, int y){ 
		printf("lambda::"); foo.bar(x, y); 
	});
	// Emit the signal !
	s.emit(4, 2);
	getchar();
	return 0;
}

foobar(4, 2)

Foo::bar(4, 2)

lambda::Foo::bar(4, 2)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115478.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 计算机考研各省份学校,想考研究生,哪个省份的高校更容易考上?

    计算机考研各省份学校,想考研究生,哪个省份的高校更容易考上?广东省2020年报考人数为17.4万,比去年增长24.3%。考研人数在过去的5年里飞速增长,自2015年的5.16万到2020年的17.4万,五年时间里翻了两倍多,涨幅在国内名列前茅。山东省2020年硕士研究生招生考试准考人数共313190人,比去年增加58704人,增幅为23.1%,同样每年新增几万的考研人。江苏省2020年共有24.9万名考生报名参加硕士研究生考试,比去年增长17.7%,再创历…

    2022年5月22日
    76
  • 强大的jQuery网格插件 ParamQuery

    强大的jQuery网格插件 ParamQuery

    2021年8月27日
    125
  • python常用库有哪些_怎么查看python的库

    python常用库有哪些_怎么查看python的库python之Sklearn库0前言1.数据集的预处理1.0下载数据1.1数据查看1.2标签清洗1.3标签编码1.4数据集得标准化1.5构建训练集和测试集2.八大分类算法2.1K近邻(KNN)2.1.1介绍2.1.2实现2.2朴素贝叶斯算法2.2.1介绍2.2.2实现2.3决策树算法2.3.1介绍2.3.2实现2.4逻辑回归2.4.1介绍2.4.2实现2.5支持向量机算法2.5.1介绍2.5.2实现2.6集成方法–随机森林2.6.1介绍2.6.2实

    2022年10月17日
    6
  • 0 can’t find referenced pointcut aApplogic

    0 can’t find referenced pointcut aApplogic0 can’t find referenced pointcut aApplogic

    2022年4月24日
    46
  • python for循环语句怎么写

    python for循环语句怎么写想必大家都知道 python 循环语句吧 可以 python 循环语句有多种 比如 for 循环 while 循环 if else 等等 今天小编就给大家讲讲 for 循环语句 for 循环语句是 python 中的一个循环控制语句 任何有序的序列对象内的元素都可以遍历 比如字符串 列表 元组等可迭代对像 之前讲过的 if 语句虽然和 for 语句用法不同 但可以用在 for 语句下做条件语句使用 for 语句的基本格式 pyth

    2025年8月10日
    4
  • Hmily:轻轻松松搞定高并发分布式事务[通俗易懂]

    Hmily:轻轻松松搞定高并发分布式事务[通俗易懂]点击上方“芋道源码”,选择“置顶公众号”技术文章第一时间送达!源码精品专栏 精尽Dubbo原理与源码 69篇精尽Netty原理与源码 61篇中文详细注释的开源…

    2022年5月11日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号