PLCnext API Documentation  22.9.0.33
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 namespace Arp
15 {
16 
17 using namespace Arp::System::Core;
18 
20 template <typename T> class delegate;
22 
23 
26 
28 // class delegate is implemented completely implicite inline to avoid
29 // code bloat in used Core classe and therefore reduce compile time
30 
46 template<class R, class ...A>
47 class delegate<R(A...)>
48 {
49 private: // typedefs/usings
50  using InvokerPtr = R(*)(void*, A && ...);
51  using FunctorPtr = std::shared_ptr<Impl::IDelegateFunctor>;
52 
53 public: // construction/destruction/assignment
55  template<class Lambda>
56  delegate(Lambda f) : delegate(new Impl::LambdaFunctor<R(A...)>(std::function<R(A...)>(f)), &Impl::LambdaFunctor<R(A...)>::Invoke) {}
58  delegate(void) = default;
61  delegate(const delegate& arg) = default;
64  delegate(delegate&& arg)noexcept = default;
68  delegate& operator=(const delegate& arg) = default;
72  delegate& operator=(delegate&& arg)noexcept = default;
73 
74 public: // static factory operations
78  static delegate create(R(*const pFunction)(A...))
79  {
80  return{ new Impl::StaticFunctor<R(A...)>(pFunction), &Impl::StaticFunctor<R(A...)>::Invoke };
81  }
82 
87  template <class C>
88  static delegate create(C* pObject, R(C::*pMethod)(A...))noexcept
89  {
90  return{ new Impl::MethodFunctor<R(C::*)(A...)>(pObject, pMethod), &Impl::MethodFunctor<R(C::*)(A...)>::Invoke };
91  }
92 
97  template <class C>
98  static delegate create(C& object, R(C::*pMethod)(A...))noexcept
99  {
100  return{ new Impl::MethodFunctor<R(C::*)(A...)>(object, pMethod), &Impl::MethodFunctor<R(C::*)(A...)>::Invoke };
101  }
102 
107  template <class C>
108  static delegate create(const C* pObject, R(C::*pMethod)(A...)const)noexcept
109  {
110  return{ new Impl::ConstMethodFunctor<R(C::*)(A...)const>(pObject, pMethod), &Impl::ConstMethodFunctor<R(C::*)(A...)const>::Invoke };
111  }
112 
117  template <class C>
118  static delegate create(const C& object, R(C::*pMethod)(A...)const)noexcept
119  {
120  return{ new Impl::ConstMethodFunctor<R(C::*)(A...)const>(object, pMethod), &Impl::ConstMethodFunctor<R(C::*)(A...)const>::Invoke };
121  }
122 
126  static delegate create(std::function<R(A...)>&& f)
127  {
128  return{ new Impl::LambdaFunctor<R(A...)>(std::move(f)), &Impl::LambdaFunctor<R(A...)>::Invoke };
129  }
130 
134  static delegate create(const std::function<R(A...)>& f)
135  {
136  return{ new Impl::LambdaFunctor<R(A...)>(f), &Impl::LambdaFunctor<R(A...)>::Invoke };
137  }
138 
139 public: // operators
143  bool operator==(const delegate& rhs)const noexcept
144  {
145  return *this->functorPtr == *rhs.functorPtr;
146  }
147 
151  bool operator!=(const delegate& rhs)const noexcept
152  {
153  return !(this->operator==(rhs));
154  }
155 
156 public: // nullptr and bool support
158  delegate(std::nullptr_t) noexcept : delegate(nullptr, nullptr) { }
159 
162  bool operator==(std::nullptr_t const)const noexcept
163  {
164  return this->functorPtr == nullptr;
165  }
166 
169  bool operator!=(std::nullptr_t const)const noexcept
170  {
171  return this->functorPtr != nullptr;
172  }
173 
176  explicit operator bool()const noexcept
177  {
178  return (bool)this->functorPtr;
179  }
180 
181 public: // property getter
184  bool is_lambda(void)const
185  {
186  return (bool)(*this) && dynamic_cast<Impl::LambdaFunctor<R(A...)>*>(this->functorPtr.get()) != nullptr;
187  }
188 
189 public: // functor operator()
193  R operator()(A... args)const
194  {
195  return this->pInvoker(this->functorPtr.get(), std::forward<A>(args)...);
196  }
197 
198 public: // management operations
201  void reset()
202  {
203  this->pInvoker = nullptr;
204  this->functorPtr = nullptr;
205  }
206 
207 private: // construction
208  delegate(Impl::IDelegateFunctor* pFunctor, InvokerPtr pInvokerArg)noexcept
209  : pInvoker(pInvokerArg)
210  , functorPtr(pFunctor)
211  {
212  }
213 
214 private: // fields
215  InvokerPtr pInvoker;
216  FunctorPtr functorPtr;
217 };
218 
220 // make_delegate factory function
224 template<class R, class ...A>
225 inline delegate<R(A...)> make_delegate(R(*const function_ptr)(A...))noexcept
226 {
227  return delegate<R(A...)>::create(function_ptr);
228 }
229 
234 template<class C, class R, class ...A>
235 inline delegate<R(A...)> make_delegate(C* const pObject, R(C::*const pMethod)(A...))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 const* const pObject, R(C::*const pMethod)(A...)const)noexcept
246 {
247  return delegate<R(A...)>::create(pObject, pMethod);
248 }
249 
254 template<class C, class R, class ...A>
255 inline delegate<R(A...)> make_delegate(C& object, R(C::*const pMethod)(A...))noexcept
256 {
257  return delegate<R(A...)>::create(object, pMethod);
258 }
259 
264 template<class C, class R, class ...A>
265 inline delegate<R(A...)> make_delegate(const C& object, R(C::*const pMethod)(A...)const)noexcept
266 {
267  return delegate<R(A...)>::create(object, pMethod);
268 }
269 
273 template<class R, class ...A>
274 inline delegate<R(A...)> make_delegate(std::function<R(A...)>&& f)noexcept
275 {
276  return delegate<R(A...)>::create(std::move(f));
277 }
278 
282 template<class R, class ...A>
283 inline delegate<R(A...)> make_delegate(const std::function<R(A...)>& f)noexcept
284 {
285  return delegate<R(A...)>::create(f);
286 }
287 
289 
290 } // end of namespace Arp
bool is_lambda(void) const
Determines if this instance wraps a lamda expression or std::function
Definition: delegate.hxx:184
bool operator!=(const delegate &rhs) const noexcept
Compares this instance to the as argument passed rhs .
Definition: delegate.hxx:151
delegate(const delegate &arg)=default
The default copy constructor.
delegate(void)=default
The default constructor.
delegate(std::nullptr_t) noexcept
Constructs an empty delegate representing a nullptr.
Definition: delegate.hxx:158
bool operator!=(std::nullptr_t const) const noexcept
Compares this instance to a nullptr.
Definition: delegate.hxx:169
static delegate create(std::function< R(A...)> &&f)
Creates a delegate from a lambda expression or std::function.
Definition: delegate.hxx:126
void reset()
Resets this instance.
Definition: delegate.hxx:201
static delegate create(R(*const pFunction)(A...))
Creates a delegate from a static function.
Definition: delegate.hxx:78
static delegate create(C &object, R(C::*pMethod)(A...)) noexcept
Creates a delegate from a member function and object reference.
Definition: delegate.hxx:98
delegate(Lambda f)
Constructs a delegate through a lambda expression implicitly.
Definition: delegate.hxx:56
delegate(delegate &&arg) noexcept=default
The default move constructor.
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:108
static delegate create(C *pObject, R(C::*pMethod)(A...)) noexcept
Creates a delegate from a member function and object pointer.
Definition: delegate.hxx:88
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:118
delegate & operator=(delegate &&arg) noexcept=default
The default move assign operator.
static delegate create(const std::function< R(A...)> &f)
Creates a delegate from a lambda expression or std::function.
Definition: delegate.hxx:134
R operator()(A... args) const
The functor operator invokes the adapted callable target.
Definition: delegate.hxx:193
delegate & operator=(const delegate &arg)=default
The default assign operator.
bool operator==(const delegate &rhs) const noexcept
Compares this instance to the as argument passed rhs .
Definition: delegate.hxx:143
bool operator==(std::nullptr_t const) const noexcept
Compares this instance to a nullptr.
Definition: delegate.hxx:162
delegate< R(A...)> make_delegate(R(*const function_ptr)(A...)) noexcept
Creates a delegate from a static function.
Definition: delegate.hxx:225
bool operator==(const BasicString< CharType, Alloc > &left, const BasicString< CharType, Alloc > &right)
Compares the left string to the right string on equality.
Definition: BasicString.hxx:1876
Root namespace for the PLCnext API
Namespace of the C++ standard library