PLCnext API Documentation  20.6.0.30321
delegate.hxx
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 #pragma once
7 #include "Arp/System/Core/Arp.h"
8 #include "Arp/System/Core/Impl/StaticFunctor.hxx"
9 #include "Arp/System/Core/Impl/MethodFunctor.hxx"
10 #include "Arp/System/Core/Impl/ConstMethodFunctor.hxx"
11 #include "Arp/System/Core/Impl/LambdaFunctor.hxx"
12 #include <memory>
13 
14 #pragma warning(disable:4100)
15 
16 namespace Arp
17 {
18 
19 using namespace Arp::System::Core;
20 
22 template <typename T> class delegate;
24 
25 
28 
30 // class delegate is implemented completely implicite inline to avoid
31 // code bloat in used Core classe and therefore reduce compile time
32 
48 template<class R, class ...A>
49 class delegate<R(A...)>
50 {
51 private: // typedefs/usings
52  using InvokerPtr = R(*)(void*, A && ...);
53  using FunctorPtr = std::shared_ptr<Impl::IDelegateFunctor>;
54 
55 public: // construction/destruction/assignment
57  delegate(void) = default;
60  delegate(const delegate& arg) = default;
63  delegate(delegate&& arg) = default;
67  delegate& operator=(const delegate& arg) = default;
71  delegate& operator=(delegate&& arg) = default;
72 
73 public: // static factory operations
77  static delegate create(R(*const pFunction)(A...))
78  {
79  return{ new Impl::StaticFunctor<R(A...)>(pFunction), &Impl::StaticFunctor<R(A...)>::Invoke };
80  }
81 
86  template <class C>
87  static delegate create(C* pObject, R(C::*pMethod)(A...))noexcept
88  {
89  return{ new Impl::MethodFunctor<R(C::*)(A...)>(pObject, pMethod), &Impl::MethodFunctor<R(C::*)(A...)>::Invoke };
90  }
91 
96  template <class C>
97  static delegate create(C& object, R(C::*pMethod)(A...))noexcept
98  {
99  return{ new Impl::MethodFunctor<R(C::*)(A...)>(object, pMethod), &Impl::MethodFunctor<R(C::*)(A...)>::Invoke };
100  }
101 
106  template <class C>
107  static delegate create(const C* pObject, R(C::*pMethod)(A...)const)noexcept
108  {
109  return{ new Impl::ConstMethodFunctor<R(C::*)(A...)const>(pObject, pMethod), &Impl::ConstMethodFunctor<R(C::*)(A...)const>::Invoke };
110  }
111 
116  template <class C>
117  static delegate create(const C& object, R(C::*pMethod)(A...)const)noexcept
118  {
119  return{ new Impl::ConstMethodFunctor<R(C::*)(A...)const>(object, pMethod), &Impl::ConstMethodFunctor<R(C::*)(A...)const>::Invoke };
120  }
121 
125  static delegate create(std::function<R(A...)>&& f)
126  {
127  return{ new Impl::LambdaFunctor<R(A...)>(std::forward<std::function<R(A...)>>(f)), &Impl::LambdaFunctor<R(A...)>::Invoke };
128  }
129 
133  static delegate create(const std::function<R(A...)>& f)
134  {
135  return{ new Impl::LambdaFunctor<R(A...)>(f), &Impl::LambdaFunctor<R(A...)>::Invoke };
136  }
137 
138 public: // operators
142  bool operator==(const delegate& rhs)const noexcept
143  {
144  return *this->functorPtr == *rhs.functorPtr;
145  }
146 
150  bool operator!=(const delegate& rhs)const noexcept
151  {
152  return !(this->operator==(rhs));
153  }
154 
155 public: // nullptr and bool support
157  delegate(std::nullptr_t) noexcept : delegate(nullptr, nullptr) { }
158 
161  bool operator==(std::nullptr_t const)const noexcept
162  {
163  return this->functorPtr == nullptr;
164  }
165 
168  bool operator!=(std::nullptr_t const)const noexcept
169  {
170  return this->functorPtr != nullptr;
171  }
172 
175  explicit operator bool()const noexcept
176  {
177  return (bool)this->functorPtr;
178  }
179 
180 public: // property getter
183  bool is_lambda(void)const
184  {
185  return (bool)(*this) && dynamic_cast<Impl::LambdaFunctor<R(A...)>*>(this->functorPtr.get()) != nullptr;
186  }
187 
188 public: // functor operator()
192  R operator()(A... args)const
193  {
194  return this->pInvoker(this->functorPtr.get(), std::forward<A>(args)...);
195  }
196 
197 private: // construction
198  delegate(Impl::IDelegateFunctor* pFunctor, InvokerPtr pInvokerArg)noexcept
199  : pInvoker(pInvokerArg)
200  , functorPtr(pFunctor)
201  {
202  }
203 
204 private: // fields
205  InvokerPtr pInvoker;
206  FunctorPtr functorPtr;
207 };
208 
210 // make_delegate factory function
214 template<class R, class ...A>
215 inline delegate<R(A...)> make_delegate(R(*const function_ptr)(A...))noexcept
216 {
217  return delegate<R(A...)>::create(function_ptr);
218 }
219 
224 template<class C, class R, class ...A>
225 inline delegate<R(A...)> make_delegate(C* const pObject, R(C::*const pMethod)(A...))noexcept
226 {
227  return delegate<R(A...)>::create(pObject, pMethod);
228 }
229 
234 template<class C, class R, class ...A>
235 inline delegate<R(A...)> make_delegate(C const* const pObject, R(C::*const pMethod)(A...)const)noexcept
236 {
237  return delegate<R(A...)>::create(pObject, pMethod);
238 }
239 
244 template<class C, class R, class ...A>
245 inline delegate<R(A...)> make_delegate(C& object, R(C::*const pMethod)(A...))noexcept
246 {
247  return delegate<R(A...)>::create(object, pMethod);
248 }
249 
254 template<class C, class R, class ...A>
255 inline delegate<R(A...)> make_delegate(const C& object, R(C::*const pMethod)(A...)const)noexcept
256 {
257  return delegate<R(A...)>::create(object, pMethod);
258 }
259 
263 template<class R, class ...A>
264 inline delegate<R(A...)> make_delegate(std::function<R(A...)>&& f)noexcept
265 {
266  return delegate<R(A...)>::create(std::forward<std::function<R(A...)>>(f));
267 }
268 
272 template<class R, class ...A>
273 inline delegate<R(A...)> make_delegate(const std::function<R(A...)>& f)noexcept
274 {
275  return delegate<R(A...)>::create(f);
276 }
277 
279 
280 } // end of namespace Arp
bool operator==(const delegate &rhs) const noexcept
Compares this instance to the as argument passed rhs .
Definition: delegate.hxx:142
delegate< R(A...)> make_delegate(R(*const function_ptr)(A...)) noexcept
Creates a delegate from a static function.
Definition: delegate.hxx:215
bool operator!=(std::nullptr_t const) const noexcept
Compares this instance to a nullptr.
Definition: delegate.hxx:168
bool is_lambda(void) const
Determines if this instance wraps a lamda expression or std::function
Definition: delegate.hxx:183
bool operator==(std::nullptr_t const) const noexcept
Compares this instance to a nullptr.
Definition: delegate.hxx:161
static delegate create(const C *pObject, R(C::*pMethod)(A...) const) noexcept
Creates a delegate from a const member function and const object pointer.
Definition: delegate.hxx:107
static delegate create(R(*const pFunction)(A...))
Creates a delegate from a static function.
Definition: delegate.hxx:77
static delegate create(C *pObject, R(C::*pMethod)(A...)) noexcept
Creates a delegate from a member function and object pointer.
Definition: delegate.hxx:87
static delegate create(std::function< R(A...)> &&f)
Creates a delegate from a lambda expression or std::function.
Definition: delegate.hxx:125
delegate(std::nullptr_t) noexcept
Constructs an empty delegate representing a nullptr.
Definition: delegate.hxx:157
Root namespace for the PLCnext API
Definition: ConstMethodFunctor.hxx:10
bool operator!=(const delegate &rhs) const noexcept
Compares this instance to the as argument passed rhs .
Definition: delegate.hxx:150
static delegate create(C &object, R(C::*pMethod)(A...)) noexcept
Creates a delegate from a member function and object reference.
Definition: delegate.hxx:97
static delegate create(const C &object, R(C::*pMethod)(A...) const) noexcept
Creates a delegate from a const member function and const object reference.
Definition: delegate.hxx:117
static delegate create(const std::function< R(A...)> &f)
Creates a delegate from a lambda expression or std::function.
Definition: delegate.hxx:133
R operator()(A... args) const
The functor operator invokes the adapted callable target.
Definition: delegate.hxx:192