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

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

/*
 * File:   main.cpp
 * Author: Vicky.H
 * Email:  [email protected]
 */
#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:  [email protected]
 */
#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)

时间: 2024-09-28 07:24:22

C++11 std::bind std::function 高级使用方法的相关文章

c++11之std::bind和function

基本测试代码 #include<iostream> #include<functional> void func(void) { std::cout << __FUNCTION__ << std::endl; } void callback(std::function<int(int,char*)> fr) { fr(1,"gdg"); } int strlength(int n,constchar* str) { retur

C++11 学习笔记 std::function和bind绑定器

一.std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法五花八门.为了统一泛化函数对象,函数指针,引用函数,成员函数的指针的各种操作,让我们可以按更统一的方式写出更加泛化的代码,C++11推出了std::function. std::function是可调用对象的包装器.它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象.通过指定它的模板参数,它可以用统一的方式处理函数,函数对象,函数指针,并允许保存和

C++11新特性应用--实现延时求值(std::function和std::bind)

说是延时求值,注意还是想搞一搞std::function和std::bind. 之前博客<C++11新特性之std::function>注意是std::function怎样实现回调函数. 如今就算是补充吧,再把std::bind进行讨论讨论. 何为Callable Objects? 就可以调用对象,比方函数指针.仿函数.类成员函数指针等都可称为可调用对象. 对象包装器 Function wrapper Class that can wrap any kind of callable eleme

std::function 和 std::bind

可调用对象 是一个函数指针 是一个具有operator()成员函数的类对象(仿函数) 是一个可被装换为函数指针的类对象 是一个类的成员(函数)指针 void func() { } struct Foo { void operator()(void) { } }; struct Bar { using fr_t = void(*)(void); static void func(void) { } operator fr_t(void) { return func; } }; struct A {

STL C++ std::bind操作例子,仿函数操作配合算法库操作

1.stl::bind 和std::mem_fun_ref系列的配合使用出现了问题,多参形式不知道如何组织.适配器的操作真心难受!!!只能迷迷糊糊地用着.要使用非质变算法时需要作用于容器时只能考虑lambda或者transfer操作.待续 // functor-adapter_p431.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <algorithm>//元素操作算法 #include <functiona

std::bind接口与实现

前言 最近想起半年前鸽下来的Haskell,重温了一下忘得精光的语法,读了几个示例程序,挺带感的,于是函数式编程的草就种得更深了.又去Google了一下C++与FP,找到了一份近乎完美的讲义,然后被带到C++20的ranges library,对即将发布的C++20满怀憧憬.此时,我猛然间意识到,看别人做,觉得自己也能做好,在游戏界叫云玩家,在编程界就叫云程序员啊! 不行,得找点事干.想起同样被我鸽了很久的<functional>系列,刚好与函数式编程搭点边,就动笔写吧!这就是本文的来历. 找

c++11 std::ref std::cref

参考: C++已经有了引用操作符&为什么C++11还要引入std:ref std::ref和std::cref使用 &是类型说明符,而std::ref是一个函数,返回std::reference_wrapper(类似于指针) 为什么需要std::ref?(std::cref类似) 主要是考虑到c++11中的函数式编程,例如:std::bind std::bind在使用时,是对参数直接拷贝,而不是引用 发现这个问题的契机是在使用thread的标准库时 #include<iostream

c++11特性与cocos2d-x 3.0之std::bind与std::function

昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 cocos2d-x 3.0rc0 差别还是相当大的. 发现Label这一个控件,3.0就比rc0版本多了一个创建函数,更为关键的是3.0内的Label锚点是在ccp(0.5,0.5),而一直3.0rc0是ccp(0,0). 累觉不爱.尽管cocos2d-x改变太快,兼容性一次次的暴露出不足,但是,总归是向好的方向进行.于是下载了3.0来玩玩~ cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码:

C++ 11 std::function std::bind使用

cocos new 出新的项目之后,仔细阅读代码,才发现了一句3.0区别于2.0的代码: auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 2.0内的代码用的不是CC_CALLBACK_1而是menu_selector. CC_CALLBACK系列是3.