16 #include <type_traits>
24 template <
typename,
typename H =
void, DelegateType = DelegateType::NonOwning>
55 template <
typename T,
typename C>
57 decltype(std::declval<T &>() = std::declval<C>());
89 template <
typename Callable,
typename = isNoFunPtr<Callable>>
96 template <
typename Callable,
typename = isNoFunPtr<Callable>>
111 template <
typename Callable,
typename = isNoFunPtr<Callable>>
118 template <
typename Callable,
typename = isNoFunPtr<Callable>>
124 template <auto Callable>
126 m_payload.payload =
nullptr;
130 decltype(Callable)>::
value,
131 "Callable given does not correspond exactly to required call "
136 return std::invoke(Callable, std::forward<Args>(
args)...);
145 template <
typename Callable,
typename = isNoFunPtr<Callable>>
147 connect<&Callable::operator(), Callable>(&callable);
152 template <
typename Callable,
typename = isNoFunPtr<Callable>>
153 void connect(Callable &&) =
delete;
161 if constexpr (kOwnership == DelegateType::NonOwning) {
162 m_payload.payload =
nullptr;
164 m_function = callable;
173 template <
auto Callable,
typename Type,
DelegateType T = kOwnership,
174 typename = std::enable_if_t<T == DelegateType::NonOwning>>
179 decltype(Callable)>::
value,
180 "Callable given does not correspond exactly to required call "
183 m_payload.payload = instance;
186 assert(payload !=
nullptr &&
"Payload is required, but not set");
187 const auto *concretePayload =
static_cast<const Type *
>(payload);
188 return std::invoke(Callable, concretePayload,
189 std::forward<Args>(
args)...);
198 template <auto Callable,
typename Type>
199 void connect(std::unique_ptr<const Type> instance) {
202 decltype(Callable)>::
value,
203 "Callable given does not correspond exactly to required call "
206 if constexpr (kOwnership == DelegateType::Owning) {
207 m_payload.payload = std::unique_ptr<const holder_type, deleter_type>(
208 instance.release(), [](
const holder_type *payload) {
209 const auto *concretePayload =
static_cast<const Type *
>(payload);
210 delete concretePayload;
213 m_payload.payload = instance.release();
217 assert(payload !=
nullptr &&
"Payload is required, but not set");
218 const auto *concretePayload =
static_cast<const Type *
>(payload);
219 return std::invoke(Callable, concretePayload,
220 std::forward<Args>(
args)...);
228 assert(connected() &&
"Delegate is not connected");
229 return std::invoke(m_function, m_payload.ptr(),
230 std::forward<Args>(
args)...);
235 bool connected()
const {
return m_function !=
nullptr; }
239 operator bool()
const {
return connected(); }
244 m_function =
nullptr;
247 template <
typename holder_t = holder_type,
248 typename = std::enable_if_t<!std::is_same_v<holder_t, void>>>
250 return m_payload.ptr();
260 struct NonOwningPayload {
261 void clear() { payload =
nullptr; }
263 const holder_type *ptr()
const {
return payload; }
265 const holder_type *payload{
nullptr};
269 struct OwningPayload {
270 void clear() { payload.reset(); }
272 const holder_type *ptr()
const {
return payload.get(); }
274 std::unique_ptr<const holder_type, deleter_type> payload{
nullptr,
279 std::conditional_t<kOwnership == DelegateType::NonOwning, NonOwningPayload,
289 template <
typename,
typename H =
void>
293 template <
typename R,
typename H,
typename...
Args>
295 :
public Delegate<R(Args...), H, DelegateType::Owning> {};