(7条消息) C++11 std::bind std::function 高级用法

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

  1. /*
  2. * File: main.cpp
  3. * Author: Vicky.H
  4. * Email: eclipser@163.com
  5. */
  6. #include <iostream>
  7. #include <functional>
  8. #include <typeinfo>
  9. #include <string.h>
  10. int add1(int i, int j, int k) {
  11. return i + j + k;
  12. }
  13. class Utils {
  14. public:
  15. Utils(const char* name) {
  16. strcpy(_name, name);
  17. }
  18. void sayHello(const char* name) const {
  19. std::cout << _name << " say: hello " << name << std::endl;
  20. }
  21. static int getId() {
  22. return 10001;
  23. }
  24. int operator()(int i, int j, int k) const {
  25. return i + j + k;
  26. }
  27. private:
  28. char _name[32];
  29. };
  30. /*
  31. *
  32. */
  33. int main(void) {
  34. // 绑定全局函数
  35. auto add2 = std::bind(add1, std::placeholders::_1, std::placeholders::_2, 10);
  36. // 函数add2 = 绑定add1函数,参数1不变,参数2不变,参数3固定为10.
  37. std::cout << typeid(add2).name() << std::endl;
  38. std::cout << "add2(1,2) = " << add2(1, 2) << std::endl;
  39. std::cout << "\n---------------------------" << std::endl;
  40. // 绑定成员函数
  41. Utils utils("Vicky");
  42. auto sayHello = std::bind(&Utils::sayHello, utils/*调用者*/, std::placeholders::_1/*参数1*/);
  43. sayHello("Jack");
  44. auto sayHelloToLucy = std::bind(&Utils::sayHello, utils/*调用者*/, "Lucy"/*固定参数1*/);
  45. sayHelloToLucy();
  46. // 绑定静态成员函数
  47. auto getId = std::bind(&Utils::getId);
  48. std::cout << getId() << std::endl;
  49. std::cout << "\n---------------------------" << std::endl;
  50. // 绑定operator函数
  51. auto add100 = std::bind(&Utils::operator (), utils, std::placeholders::_1, std::placeholders::_2, 100);
  52. std::cout << "add100(1, 2) = " << add100(1, 2) << std::endl;
  53. // 注意:无法使用std::bind()绑定一个重载函数
  54. return 0;
  55. }

  1. /*
  2. * File: main2.cpp
  3. * Author: Vicky.H
  4. * Email: eclipser@163.com
  5. */
  6. #include <iostream>
  7. #include <typeinfo>
  8. void sayHello() {
  9. std::cout << "Hello world !" << std::endl;
  10. }
  11. int sum(int i, int j, int k) {
  12. return i + j + k;
  13. }
  14. template <typename T>
  15. class Func {
  16. public:
  17. Func(T fun) {
  18. if (!fun) {
  19. throw "fun nullptr";
  20. }
  21. _fun = fun;
  22. }
  23. template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
  24. R Call(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
  25. return _fun(a1, a2, a3, a4, a5);
  26. }
  27. template<typename R, typename A1, typename A2, typename A3, typename A4>
  28. R Call(A1 a1, A2 a2, A3 a3, A4 a4) {
  29. return _fun(a1, a2, a3, a4);
  30. }
  31. template<typename R, typename A1, typename A2, typename A3>
  32. R Call(A1 a1, A2 a2, A3 a3) {
  33. return _fun(a1, a2, a3);
  34. }
  35. template<typename R, typename A1, typename A2>
  36. R Call(A1 a1, A2 a2) {
  37. return _fun(a1, a2);
  38. }
  39. template<typename R, typename A1>
  40. R Call(A1 a1) {
  41. return _fun(a1);
  42. }
  43. template<typename R>
  44. R Call() {
  45. return _fun();
  46. }
  47. void Call() {
  48. _fun();
  49. }
  50. private:
  51. T _fun;
  52. };
  53. #include <functional>
  54. template<typename R = void, typename... Args>
  55. class Fn {
  56. public:
  57. Fn(std::function<R(Args...)> fun) : _fun(fun) {
  58. }
  59. R operator()(Args... args) {
  60. return _fun(args...);
  61. }
  62. private:
  63. std::function<R(Args...) > _fun;
  64. };
  65. /*
  66. * 将函数注册到对象中,通过对象直接调用
  67. */
  68. int main(void) {
  69. Func<void(*)() > sayHelloFunc(sayHello);
  70. sayHelloFunc.Call();
  71. Func<int (*)(int, int, int) > sumFunc(sum);
  72. std::cout << "sumFunc.Call<int>(1, 2, 3) : " << sumFunc.Call<int>(1, 2, 3) << std::endl;
  73. std::cout << "\n---------------------------" << std::endl;
  74. Fn<> sayHelloFn(sayHello);
  75. sayHelloFn();
  76. Fn<int, int, int, int> sumFn(sum);
  77. std::cout << "sumFn(1, 2, 3) : " << sumFn(1, 2, 3) << std::endl;
  78. std::cout << "\n---------------------------" << std::endl;
  79. return 0;
  80. }


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
这篇文章中,无法直接调用脚本函数类,有了好的解决办法。这个我将随后补充。

  1. #include <list>
  2. #include <functional>
  3. template<typename... Args>
  4. class Fns
  5. {
  6. private:
  7. std::list<std::function<void(Args...)> > _calls;
  8. public:
  9. virtual ~Fns()
  10. {
  11. _calls.clear();
  12. }
  13. void connect(std::function<void(Args...)> fct)
  14. {
  15. _calls.push_back(fct);
  16. }
  17. template<typename Object>
  18. void connect(Object* object, void (Object::*method)(Args...))
  19. {
  20. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});
  21. }
  22. template<typename Object>
  23. void connect(Object* object, void (Object::*method)(Args...) const)
  24. {
  25. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});
  26. }
  27. template<typename Object>
  28. void connect(const Object* object, void (Object::*method)(Args...) const)
  29. {
  30. _calls.push_back([object,method](Args... args){(*object.*method)(args...);});
  31. }
  32. void emit(Args... args)
  33. {
  34. for(auto call : _calls)
  35. call(args...);
  36. }
  37. };

  1. #include <cstdio>
  2. #include "Signal.hpp"
  3. class Foo
  4. {
  5. public:
  6. void bar(int x, int y)
  7. {
  8. printf("Foo::bar(%d, %d)\n", x, y);
  9. }
  10. };
  11. void foobar(int x, int y)
  12. {
  13. printf("foobar(%d, %d)\n", x, y);
  14. }
  15. int main(void)
  16. {
  17. Foo foo;
  18. Fns<int, int> s;
  19. // Connect a function
  20. s.connect(foobar);
  21. // Connect a class method
  22. s.connect(&foo, &Foo::bar);
  23. // Create and connect some lambda expression
  24. s.connect([&foo](int x, int y){
  25. printf("lambda::"); foo.bar(x, y);
  26. });
  27. // Emit the signal !
  28. s.emit(4, 2);
  29. getchar();
  30. return 0;
  31. }


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

(0)

相关推荐