fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <memory>
  4. using namespace std;
  5.  
  6. template<typename ReturnType, typename... Arguments>
  7. class FunctionImplBase
  8. {
  9. public:
  10. virtual ~FunctionImplBase() {}
  11. virtual ReturnType call(Arguments... arguments) = 0;
  12. };
  13.  
  14. template <typename Callable, typename ReturnType, typename... Arguments>
  15. class FunctionImpl : public FunctionImplBase<ReturnType, Arguments...>
  16. {
  17. public:
  18. explicit FunctionImpl(const Callable& aCallable) : mCallable(aCallable) {}
  19.  
  20. ReturnType call(Arguments... aArguments) override
  21. {
  22. return mCallable(std::forward<Arguments>(aArguments)...);
  23. }
  24. private:
  25. Callable mCallable;
  26. };
  27.  
  28.  
  29. template<typename Signature>
  30. class Function;
  31.  
  32. template<typename ReturnType, typename... Arguments>
  33. class Function<ReturnType(Arguments...)>
  34. {
  35. public:
  36. Function() {}
  37.  
  38. template <typename Callable>
  39. explicit Function(Callable aCallable)
  40. : mImpl(std::make_unique<FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable))
  41. {}
  42.  
  43. template <typename Callable>
  44. Function& operator=(const Callable& aCallable)
  45. {
  46. mImpl = std::make_unique<FunctionImpl<Callable, ReturnType, Arguments...>>(aCallable);
  47. return *this;
  48. }
  49.  
  50. ReturnType operator()(Arguments... aArguments) const
  51. {
  52. return mImpl->call(std::forward<Arguments>(aArguments)...);
  53. }
  54. private:
  55. std::unique_ptr<FunctionImplBase<ReturnType, Arguments...>> mImpl;
  56. };
  57.  
  58. struct Foo
  59. {
  60. public:
  61. Foo() {
  62. std::cout << "ctor this:" << this << std::endl;
  63. }
  64.  
  65. Foo(const Foo &ref) {
  66. std::cout << "copy this:" << this << " ref:" << &ref << std::endl;
  67. }
  68.  
  69. Foo(Foo &&ref) {
  70. std::cout << "move this:" << this << " ref:" << &ref << std::endl;
  71. }
  72.  
  73. ~Foo() {
  74. std::cout << "dtor this:" << this << std::endl;
  75. }
  76.  
  77. Foo &operator=(const Foo &rhs) {
  78. cout<<"copy assignment"<<endl;
  79. return (*this);
  80. }
  81.  
  82. Foo&operator=(Foo&& rhs)
  83. {
  84. cout<<"move assignment"<<endl;
  85. return *this;
  86. }
  87. };
  88. void Bar(Foo f){};
  89. int main()
  90. {
  91. Foo f;
  92.  
  93. //Function<void(Foo)> func = &Bar; //Error, since explicit
  94. Function<void(Foo)> func (&Bar);
  95. cout<<"invoke +++"<<endl;
  96. func(f);
  97. cout<<"invoke ---"<<endl;
  98.  
  99.  
  100. cout<<"std::function invoke ++"<<endl;
  101. std::function<void(Foo)> std_func = &Bar;
  102. std_func(f);
  103. cout<<"std::function invoke --"<<endl;
  104. return 0;
  105. }
  106.  
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
ctor this:0xbffc09ab
invoke +++
copy this:0xbffc09ac ref:0xbffc09ab
move this:0xbffc09ae ref:0xbffc09ac
move this:0xbffc09af ref:0xbffc09ae
dtor this:0xbffc09af
dtor this:0xbffc09ae
dtor this:0xbffc09ac
invoke ---
std::function invoke ++
copy this:0xbffc09ad ref:0xbffc09ab
move this:0xbffc095f ref:0xbffc09ad
dtor this:0xbffc095f
dtor this:0xbffc09ad
std::function invoke --
dtor this:0xbffc09ab