Loading...
Searching...
No Matches
delegate_cpp11.h
Go to the documentation of this file.
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2019 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
/******************************************************************************
Copyright (C) 2017 by Sergey A Kryukov: derived work
http://www.SAKryukov.org
http://www.codeproject.com/Members/SAKryukov
Based on original work by Sergey Ryazanov:
"The Impossibly Fast C++ Delegates", 18 Jul 2005
https://www.codeproject.com/articles/11015/the-impossibly-fast-c-delegates
MIT license:
http://en.wikipedia.org/wiki/MIT_License
Original publication:
https://www.codeproject.com/Articles/1170503/The-Impossibly-Fast-Cplusplus-Delegates-Fixed
******************************************************************************/
#ifndef ETL_DELEGATE_CPP11_INCLUDED
#define ETL_DELEGATE_CPP11_INCLUDED
#include "../platform.h"
#include "../error_handler.h"
#include "../exception.h"
#include "../function_traits.h"
#include "../optional.h"
#include "../type_list.h"
#include "../type_traits.h"
#include "../utility.h"
namespace etl
{
//***************************************************************************
//***************************************************************************
class delegate_exception : public exception
{
public:
delegate_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class delegate_uninitialised : public delegate_exception
{
public:
delegate_uninitialised(string_type file_name_, numeric_type line_number_)
: delegate_exception(ETL_ERROR_TEXT("delegate:uninitialised", ETL_DELEGATE_FILE_ID"A"), file_name_, line_number_)
{
}
};
//*****************************************************************
//*****************************************************************
struct delegate_tag
{
};
//***************************************************************************
//***************************************************************************
template <typename T>
struct is_delegate : etl::bool_constant<etl::is_base_of<delegate_tag, T>::value>
{
};
#if ETL_USING_CPP17
template <typename T>
inline constexpr bool is_delegate_v = is_delegate<T>::value;
#endif
//*************************************************************************
//*************************************************************************
template <typename T>
class delegate;
//*************************************************************************
//*************************************************************************
template <typename TReturn, typename... TArgs>
class delegate<TReturn(TArgs...)> final : public delegate_tag
{
private:
using object_ptr = void*;
using function_ptr = TReturn (*)(TArgs...);
public:
using return_type = TReturn;
using argument_types = etl::type_list<TArgs...>;
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
{
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate(const delegate& other) = default;
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(const TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), const_lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
template <typename TLambda,
typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TArgs...)>, TLambda>::value
&& !etl::is_convertible<TLambda, function_ptr>::value,
void>>
ETL_CONSTEXPR14 delegate(TLambda&& instance) = delete;
//*************************************************************************
//*************************************************************************
explicit ETL_CONSTEXPR14 delegate(function_ptr fp) ETL_NOEXCEPT
: invocation(fp, function_ptr_stub)
{
}
//*************************************************************************
//*************************************************************************
template <TReturn (*Method)(TArgs...)>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(function_stub<Method>);
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(TLambda& instance) ETL_NOEXCEPT
{
return delegate(object_ptr(&instance), lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(const TLambda& instance) ETL_NOEXCEPT
{
return delegate(object_ptr(&instance), const_lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(function_ptr fp) ETL_NOEXCEPT
{
return delegate(fp, function_ptr_stub);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...)>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(T& instance) ETL_NOEXCEPT
{
return delegate(object_ptr(&instance), method_stub<T, Method>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...)>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create(const T& instance) ETL_NOEXCEPT
{
return delegate(object_ptr(&instance), const_method_stub<T, Method>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const>
static ETL_CONSTEXPR14 delegate create(T&& instance) = delete;
//*************************************************************************
//*************************************************************************
template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(const_method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(const_method_instance_stub<T, Method, Instance>);
}
#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
//*************************************************************************
//*************************************************************************
template <typename T, T& Instance>
ETL_NODISCARD
static ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
{
return delegate(operator_instance_stub<T, Instance>);
}
#endif
//*************************************************************************
//*************************************************************************
template <TReturn (*Method)(TArgs...)>
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
{
assign(function_stub<Method>);
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 void set(TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 void set(const TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), const_lambda_stub<TLambda>);
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 void set(function_ptr fp) ETL_NOEXCEPT
{
assign(fp, function_ptr_stub);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...)>
ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), method_stub<T, Method>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const>
ETL_CONSTEXPR14 void set(T& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), const_method_stub<T, Method>);
}
//*************************************************************************
//*************************************************************************
template <typename T, T& Instance, TReturn (T::*Method)(TArgs...)>
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
{
assign(method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
{
assign(method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, T const& Instance, TReturn (T::*Method)(TArgs...) const>
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
{
assign(const_method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const, T const& Instance>
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
{
assign(const_method_instance_stub<T, Method, Instance>);
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
{
invocation.clear();
}
//*************************************************************************
//*************************************************************************
template <typename... TCallArgs>
ETL_CONSTEXPR14 return_type operator()(TCallArgs&&... args) const
{
ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
"Incompatible parameter types passed to delegate");
ETL_ASSERT(is_valid(), ETL_ERROR(delegate_uninitialised));
return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
template <typename TRet = TReturn, typename... TCallArgs>
ETL_CONSTEXPR14 typename etl::enable_if_t<etl::is_same<TRet, void>::value, bool> call_if(TCallArgs&&... args) const
{
ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
"Incompatible parameter types passed to delegate");
if (is_valid())
{
(*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
return true;
}
else
{
return false;
}
}
//*************************************************************************
//*************************************************************************
template <typename TRet = TReturn, typename... TCallArgs>
ETL_CONSTEXPR14 typename etl::enable_if_t<!etl::is_same<TRet, void>::value, etl::optional<TReturn>> call_if(TCallArgs&&... args) const
{
ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
"Incompatible parameter types passed to delegate");
etl::optional<TReturn> result;
if (is_valid())
{
result = (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
}
return result;
}
//*************************************************************************
//*************************************************************************
template <typename TAlternative, typename... TCallArgs>
ETL_CONSTEXPR14 TReturn call_or(TAlternative&& alternative, TCallArgs&&... args) const
{
ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
"Incompatible parameter types passed to delegate");
if (is_valid())
{
return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
}
else
{
return etl::forward<TAlternative>(alternative)(etl::forward<TCallArgs>(args)...);
}
}
//*************************************************************************
//*************************************************************************
template <TReturn (*Method)(TArgs...), typename... TCallArgs>
ETL_CONSTEXPR14 TReturn call_or(TCallArgs&&... args) const
{
ETL_STATIC_ASSERT((sizeof...(TCallArgs) == sizeof...(TArgs)), "Incorrect number of parameters passed to delegate");
ETL_STATIC_ASSERT((etl::type_lists_are_convertible<etl::type_list<TCallArgs&&...>, argument_types>::value),
"Incompatible parameter types passed to delegate");
if (is_valid())
{
return (*invocation.stub)(invocation, etl::forward<TCallArgs>(args)...);
}
else
{
return (Method)(etl::forward<TCallArgs>(args)...);
}
}
//*************************************************************************
//*************************************************************************
delegate& operator=(const delegate& rhs) = default;
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate& operator=(TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), lambda_stub<TLambda>);
return *this;
}
//*************************************************************************
//*************************************************************************
template < typename TLambda, typename = etl::enable_if_t< etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate& operator=(const TLambda& instance) ETL_NOEXCEPT
{
assign(object_ptr(&instance), const_lambda_stub<TLambda>);
return *this;
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate& operator=(function_ptr fp) ETL_NOEXCEPT
{
if (fp == ETL_NULLPTR)
{
invocation.clear();
}
else
{
assign(fp, function_ptr_stub);
}
return *this;
}
//*************************************************************************
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate& rhs) const ETL_NOEXCEPT
{
return invocation == rhs.invocation;
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 bool operator!=(const delegate& rhs) const ETL_NOEXCEPT
{
return invocation != rhs.invocation;
}
//*************************************************************************
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
{
// GCC's UBSan instruments function pointer comparisons, which prevents
// constexpr evaluation. Use implicit bool conversion at compile time
// to avoid the instrumented != comparison while still checking validity.
if (etl::is_constant_evaluated())
{
return static_cast<bool>(invocation.stub);
}
return invocation.stub != ETL_NULLPTR;
}
//*************************************************************************
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 operator bool() const ETL_NOEXCEPT
{
return is_valid();
}
private:
//*************************************************************************
// Callable compatibility: detects if C (or const C) is invocable with
// (TArgs...) and returns a type convertible to TReturn. Works with generic
// lambdas and functors.
template <typename TCallableType, typename = void>
struct is_invocable_with : etl::false_type
{
};
template <typename TCallableType>
struct is_invocable_with< TCallableType, etl::void_t<decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...))>>
: etl::bool_constant< etl::is_convertible< decltype(etl::declval<TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
{
};
template <typename TCallableType, typename = void>
struct is_invocable_with_const : etl::false_type
{
};
template <typename TCallableType>
struct is_invocable_with_const< TCallableType, etl::void_t<decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...))>>
: etl::bool_constant< etl::is_convertible< decltype(etl::declval<const TCallableType&>()(etl::declval<TArgs>()...)), TReturn>::value>
{
};
template <typename TCallableType>
struct is_compatible_callable : etl::bool_constant<is_invocable_with<TCallableType>::value || is_invocable_with_const<TCallableType>::value>
{
};
//*************************************************************************
//*************************************************************************
struct invocation_element
{
using stub_type = TReturn (*)(const invocation_element&, TArgs...);
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 invocation_element() ETL_NOEXCEPT
: ptr(object_ptr(ETL_NULLPTR))
, stub(ETL_NULLPTR)
{
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 invocation_element(stub_type stub_) ETL_NOEXCEPT
: ptr()
, stub(stub_)
{
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 invocation_element(object_ptr object_, stub_type stub_) ETL_NOEXCEPT
: ptr(object_)
, stub(stub_)
{
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 invocation_element(function_ptr fp_, stub_type stub_) ETL_NOEXCEPT
: ptr(fp_)
, stub(stub_)
{
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 bool operator==(const invocation_element& rhs) const ETL_NOEXCEPT
{
return (rhs.stub == stub) && ((stub == function_ptr_stub) ? (rhs.ptr.fp == ptr.fp) : (rhs.ptr.object == ptr.object));
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 bool operator!=(const invocation_element& rhs) const ETL_NOEXCEPT
{
return !operator==(rhs);
}
//***********************************************************************
//***********************************************************************
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
{
stub = ETL_NULLPTR;
}
//***********************************************************************
//***********************************************************************
union ptr_type
{
ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
: object(ETL_NULLPTR)
{
}
ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
: object(object_)
{
}
ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
: fp(fp_)
{
}
object_ptr object;
function_ptr fp;
};
ptr_type ptr;
stub_type stub;
};
using stub_type = typename invocation_element::stub_type;
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate(object_ptr object, stub_type stub) ETL_NOEXCEPT
: invocation(object, stub)
{
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate(function_ptr fp, stub_type stub) ETL_NOEXCEPT
: invocation(fp, stub)
{
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 delegate(stub_type stub) ETL_NOEXCEPT
: invocation(stub)
{
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 void assign(object_ptr object, stub_type stub) ETL_NOEXCEPT
{
invocation.ptr.object = object;
invocation.stub = stub;
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 void assign(function_ptr fp, stub_type stub) ETL_NOEXCEPT
{
invocation.ptr.fp = fp;
invocation.stub = stub;
}
//*************************************************************************
//*************************************************************************
ETL_CONSTEXPR14 void assign(stub_type stub) ETL_NOEXCEPT
{
invocation.ptr.object = ETL_NULLPTR;
invocation.stub = stub;
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...)>
static ETL_CONSTEXPR14 TReturn method_stub(const invocation_element& invocation, TArgs... args)
{
T* p = static_cast<T*>(invocation.ptr.object);
return (p->*Method)(etl::forward<TArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const>
static ETL_CONSTEXPR14 TReturn const_method_stub(const invocation_element& invocation, TArgs... args)
{
T* const p = static_cast<T*>(invocation.ptr.object);
return (p->*Method)(etl::forward<TArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...), T& Instance>
static ETL_CONSTEXPR14 TReturn method_instance_stub(const invocation_element&, TArgs... args)
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
template <typename T, TReturn (T::*Method)(TArgs...) const, const T& Instance>
static ETL_CONSTEXPR14 TReturn const_method_instance_stub(const invocation_element&, TArgs... args)
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
#if !(defined(ETL_COMPILER_GCC) && (__GNUC__ <= 8))
//*************************************************************************
//*************************************************************************
template <typename T, T& Instance>
static ETL_CONSTEXPR14 TReturn operator_instance_stub(const invocation_element&, TArgs... args)
{
return Instance.operator()(etl::forward<TArgs>(args)...);
}
#endif
//*************************************************************************
//*************************************************************************
template <TReturn (*Method)(TArgs...)>
static ETL_CONSTEXPR14 TReturn function_stub(const invocation_element&, TArgs... args)
{
return (Method)(etl::forward<TArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
static TReturn function_ptr_stub(const invocation_element& invocation, TArgs... args)
{
return invocation.ptr.fp(etl::forward<TArgs>(args)...);
}
//*************************************************************************
//*************************************************************************
template <typename TLambda>
static ETL_CONSTEXPR14 TReturn lambda_stub(const invocation_element& invocation, TArgs... arg)
{
ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
TLambda* p = static_cast<TLambda*>(invocation.ptr.object);
return (p->operator())(etl::forward<TArgs>(arg)...);
}
//*************************************************************************
//*************************************************************************
template <typename TLambda>
static ETL_CONSTEXPR14 TReturn const_lambda_stub(const invocation_element& invocation, TArgs... arg)
{
ETL_STATIC_ASSERT(is_compatible_callable<TLambda>::value, "etl::delegate: bound lambda/functor is not compatible with the delegate signature");
const TLambda* p = static_cast<const TLambda*>(invocation.ptr.object);
return (p->operator())(etl::forward<TArgs>(arg)...);
}
//*************************************************************************
//*************************************************************************
invocation_element invocation;
};
#if ETL_USING_CPP17
//*************************************************************************
//*************************************************************************
template <auto Function>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Function)>::function_type;
return etl::delegate<function_type>::template create<Function>();
}
//*************************************************************************
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value, void>>
ETL_NODISCARD
constexpr auto make_delegate(TLambda& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits< decltype(&TLambda::operator())>::function_type;
return etl::delegate<function_type>(instance);
}
//*************************************************************************
//*************************************************************************
template <typename T, T& Instance>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(&T::operator())>::function_type;
return etl::delegate<function_type>::template create<T, Instance>();
}
//*************************************************************************
//*************************************************************************
template <typename T, auto Method, T& Instance, typename = etl::enable_if_t< !etl::function_traits<decltype(Method)>::is_const>>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method, Instance>();
}
//*************************************************************************
//*************************************************************************
template <typename T, auto Method, const T& Instance, typename = etl::enable_if_t< etl::function_traits<decltype(Method)>::is_const>>
ETL_NODISCARD
constexpr auto make_delegate() ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method, Instance>();
}
//*************************************************************************
//*************************************************************************
template <typename T, auto Method>
ETL_NODISCARD
constexpr auto make_delegate(T& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method>(instance);
}
//*************************************************************************
//*************************************************************************
template <typename T, auto Method>
ETL_NODISCARD
constexpr auto make_delegate(const T& instance) ETL_NOEXCEPT
{
using function_type = typename etl::function_traits<decltype(Method)>::function_type;
return etl::delegate<function_type>::template create<T, Method>(instance);
}
#endif
} // namespace etl
#endif
etl::delegate< TReturn(TArgs...)>::operator==
ETL_NODISCARD ETL_CONSTEXPR14 bool operator==(const delegate &rhs) const ETL_NOEXCEPT
Checks equality.
Definition delegate_cpp11.h:557
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:211
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate(const delegate &other)=default
Copy constructor.
etl::delegate< TReturn(TArgs...)>::operator!=
ETL_CONSTEXPR14 bool operator!=(const delegate &rhs) const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:565
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set(function_ptr fp) ETL_NOEXCEPT
Set from a function pointer.
Definition delegate_cpp11.h:344
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set(TLambda &instance) ETL_NOEXCEPT
Set from Lambda or Functor.
Definition delegate_cpp11.h:327
etl::delegate< TReturn(TArgs...)>::clear
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
Clear the delegate.
Definition delegate_cpp11.h:408
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate(const TLambda &instance) ETL_NOEXCEPT
Construct from a const lambda or functor.
Definition delegate_cpp11.h:163
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from function (Compile time).
Definition delegate_cpp11.h:318
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Definition delegate_cpp11.h:308
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(T &instance) ETL_NOEXCEPT
Create from instance method (Run time).
Definition delegate_cpp11.h:230
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate(function_ptr fp) ETL_NOEXCEPT
Construct from a function pointer.
Definition delegate_cpp11.h:181
etl::delegate< TReturn(TArgs...)>::call_or
ETL_CONSTEXPR14 TReturn call_or(TCallArgs &&... args) const
Definition delegate_cpp11.h:497
etl::delegate< TReturn(TArgs...)>::operator=
ETL_CONSTEXPR14 delegate & operator=(function_ptr fp) ETL_NOEXCEPT
Assign from a function pointer.
Definition delegate_cpp11.h:541
etl::delegate< TReturn(TArgs...)>::operator=
delegate & operator=(const delegate &rhs)=default
Assignment.
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate(TLambda &&instance)=delete
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from function (Compile time).
Definition delegate_cpp11.h:191
etl::delegate< TReturn(TArgs...)>::create
static ETL_CONSTEXPR14 delegate create(T &&instance)=delete
Disable create from rvalue instance method (Run time).
etl::delegate< TReturn(TArgs...)>::argument_types
etl::type_list< TArgs... > argument_types
Type list of the delegate's argument types.
Definition delegate_cpp11.h:136
etl::delegate< TReturn(TArgs...)>::call_if
ETL_CONSTEXPR14 etl::enable_if_t< etl::is_same< TRet, void >::value, bool > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:433
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(T &&instance)=delete
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(TLambda &instance) ETL_NOEXCEPT
Create from Lambda or Functor.
Definition delegate_cpp11.h:201
etl::delegate< TReturn(TArgs...)>::operator()
ETL_CONSTEXPR14 return_type operator()(TCallArgs &&... args) const
Execute the delegate.
Definition delegate_cpp11.h:417
etl::delegate< TReturn(TArgs...)>::call_or
ETL_CONSTEXPR14 TReturn call_or(TAlternative &&alternative, TCallArgs &&... args) const
Definition delegate_cpp11.h:476
etl::delegate< TReturn(TArgs...)>::operator=
ETL_CONSTEXPR14 delegate & operator=(TLambda &instance) ETL_NOEXCEPT
Create from Lambda or Functor.
Definition delegate_cpp11.h:522
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate() ETL_NOEXCEPT
Default constructor.
Definition delegate_cpp11.h:141
etl::delegate< TReturn(TArgs...)>::return_type
TReturn return_type
The delegate's return type.
Definition delegate_cpp11.h:133
etl::delegate< TReturn(TArgs...)>::delegate
ETL_CONSTEXPR14 delegate(TLambda &instance) ETL_NOEXCEPT
Construct from a lambda or functor.
Definition delegate_cpp11.h:154
etl::delegate< TReturn(TArgs...)>::operator=
ETL_CONSTEXPR14 delegate & operator=(const TLambda &instance) ETL_NOEXCEPT
Create from const Lambda or Functor.
Definition delegate_cpp11.h:532
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create() ETL_NOEXCEPT
Create from instance method (Compile time).
Definition delegate_cpp11.h:264
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(const T &instance) ETL_NOEXCEPT
Create from const instance method (Run time).
Definition delegate_cpp11.h:248
etl::delegate< TReturn(TArgs...)>::create
static ETL_NODISCARD ETL_CONSTEXPR14 delegate create(function_ptr fp) ETL_NOEXCEPT
Create from a function pointer.
Definition delegate_cpp11.h:220
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set() ETL_NOEXCEPT
Set from instance method (Compile time).
Definition delegate_cpp11.h:371
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set(T &instance) ETL_NOEXCEPT
Set from instance method (Run time).
Definition delegate_cpp11.h:353
etl::delegate< TReturn(TArgs...)>::set
ETL_CONSTEXPR14 void set(const TLambda &instance) ETL_NOEXCEPT
Set from const Lambda or Functor.
Definition delegate_cpp11.h:336
etl::delegate< TReturn(TArgs...)>::call_if
ETL_CONSTEXPR14 etl::enable_if_t<!etl::is_same< TRet, void >::value, etl::optional< TReturn > > call_if(TCallArgs &&... args) const
Definition delegate_cpp11.h:455
etl::delegate< TReturn(TArgs...)>::is_valid
ETL_NODISCARD ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT
Returns true if the delegate is valid.
Definition delegate_cpp11.h:573
etl::delegate_exception
The base class for delegate exceptions.
Definition delegate_cpp03.h:149
etl::delegate_uninitialised
The exception thrown when the delegate is uninitialised.
Definition delegate_cpp03.h:162
etl::delegate
Declaration.
Definition delegate_cpp03.h:191
error_handler.h
exception.h
function_traits.h
ETL_ASSERT
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
etl::exception::exception
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
etl::exception
Definition exception.h:59
etl::optional
Definition optional.h:1238
etl
Definition absolute.h:40
etl::false_type
integral_constant< bool, false > false_type
integral_constant specialisations
Definition type_traits.h:80
optional.h
platform.h
etl::bool_constant
Definition type_traits.h:97
etl::delegate_tag
Definition delegate_cpp03.h:176
etl::is_delegate
is_delegate
Definition delegate_cpp03.h:184
operator==
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
operator!=
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937
type_traits.h
etl::delegate< TReturn(TArgs...)>::invocation_element::ptr_type::ptr_type
ETL_CONSTEXPR14 ptr_type(object_ptr object_) ETL_NOEXCEPT
Constructs with the object pointer as the active member.
Definition delegate_cpp11.h:708
etl::delegate< TReturn(TArgs...)>::invocation_element::ptr_type::ptr_type
ETL_CONSTEXPR14 ptr_type(function_ptr fp_) ETL_NOEXCEPT
Constructs with the function pointer as the active member.
Definition delegate_cpp11.h:714
etl::delegate< TReturn(TArgs...)>::invocation_element::ptr_type::ptr_type
ETL_CONSTEXPR14 ptr_type() ETL_NOEXCEPT
Default-constructs with a null object pointer as the active member.
Definition delegate_cpp11.h:702
utility.h