Skip to content

Commit

Permalink
etl/delegate: fix accident creation of a delegate to an rvalue delega…
Browse files Browse the repository at this point in the history
…te when copying/assigning from delegate with mismatching signature (#965)

* etl/delegate: fix accident creation of a delegate to an rvalue delegate when copying/assigning from delegate with mismatching signature

* etl/type_traits: fix etl::is_base_of for the case when TDerived is final

* add etl::is_delegate

* add changes related to etl::is_delegate to c++03 implementation

* add etl::is_delegate_v<T>
  • Loading branch information
VladimirP1 authored Oct 21, 2024
1 parent 081e920 commit 71b691f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 35 deletions.
53 changes: 35 additions & 18 deletions include/etl/private/delegate_cpp03.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,34 @@ namespace etl
}
};

//*****************************************************************
/// The tag to identify an etl::delegate.
///\ingroup delegate
//*****************************************************************
struct delegate_tag
{
};

//***************************************************************************
/// is_delegate
//***************************************************************************
template <typename T>
struct is_delegate
{
static const bool value = etl::is_base_of<delegate_tag, T>::value;
};

//*************************************************************************
/// Declaration.
//*************************************************************************
template <typename T>
class delegate;

template <typename TReturn, typename TParam>
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>, public delegate_tag
{
private:

typedef delegate<TReturn(TParam)> delegate_type;

public:
Expand All @@ -204,7 +221,7 @@ namespace etl
// Construct from a functor.
//*************************************************************************
template <typename TFunctor>
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), functor_stub<TFunctor>);
}
Expand All @@ -213,7 +230,7 @@ namespace etl
// Construct from a const functor.
//*************************************************************************
template <typename TFunctor>
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
}
Expand All @@ -232,7 +249,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value &&!etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value &&!is_delegate<TFunctor>::value, delegate>::type
create(TFunctor& instance)
{
return delegate((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -243,7 +260,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(const TFunctor& instance)
{
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down Expand Up @@ -330,7 +347,7 @@ namespace etl
/// Set from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -340,7 +357,7 @@ namespace etl
/// Set from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down Expand Up @@ -467,7 +484,7 @@ namespace etl
/// Create from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -478,7 +495,7 @@ namespace etl
/// Create from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down Expand Up @@ -705,7 +722,7 @@ namespace etl
// Construct from functor.
//*************************************************************************
template <typename TFunctor>
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), functor_stub<TFunctor>);
}
Expand All @@ -714,7 +731,7 @@ namespace etl
// Construct from const functor.
//*************************************************************************
template <typename TFunctor>
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
}
Expand All @@ -733,7 +750,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(TFunctor& instance)
{
return delegate((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -744,7 +761,7 @@ namespace etl
//*************************************************************************
template <typename TFunctor>
static
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
create(const TFunctor& instance)
{
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down Expand Up @@ -831,7 +848,7 @@ namespace etl
/// Set from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -841,7 +858,7 @@ namespace etl
/// Set from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
set(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down Expand Up @@ -968,7 +985,7 @@ namespace etl
/// Create from Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(TFunctor& instance)
{
assign((void*)(&instance), functor_stub<TFunctor>);
Expand All @@ -979,7 +996,7 @@ namespace etl
/// Create from const Functor.
//*************************************************************************
template <typename TFunctor>
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
operator =(const TFunctor& instance)
{
assign((void*)(&instance), const_functor_stub<TFunctor>);
Expand Down
45 changes: 35 additions & 10 deletions include/etl/private/delegate_cpp11.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,41 @@ namespace etl
}
};

//*****************************************************************
/// The tag to identify an etl::delegate.
///\ingroup delegate
//*****************************************************************
struct delegate_tag
{
};

//***************************************************************************
/// is_delegate
//***************************************************************************
template <typename T>
struct is_delegate
{
static constexpr bool value = 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

//*************************************************************************
/// Declaration.
//*************************************************************************
template <typename T> class delegate;
template <typename T>
class delegate;

//*************************************************************************
/// Specialisation.
//*************************************************************************
template <typename TReturn, typename... TParams>
class delegate<TReturn(TParams...)> final
class delegate<TReturn(TParams...)> final : public delegate_tag
{
public:

Expand All @@ -111,7 +136,7 @@ namespace etl
//*************************************************************************
// Construct from lambda or functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
Expand All @@ -120,7 +145,7 @@ namespace etl
//*************************************************************************
// Construct from const lambda or functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate(const TLambda& instance)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
Expand All @@ -139,7 +164,7 @@ namespace etl
//*************************************************************************
/// Create from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
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)
{
Expand All @@ -149,7 +174,7 @@ namespace etl
//*************************************************************************
/// Create from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
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)
{
Expand Down Expand Up @@ -257,7 +282,7 @@ namespace etl
//*************************************************************************
/// Set from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 void set(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
Expand All @@ -266,7 +291,7 @@ namespace etl
//*************************************************************************
/// Set from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
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)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
Expand Down Expand Up @@ -427,7 +452,7 @@ namespace etl
//*************************************************************************
/// Create from Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
ETL_CONSTEXPR14 delegate& operator =(TLambda& instance)
{
assign((void*)(&instance), lambda_stub<TLambda>);
Expand All @@ -437,7 +462,7 @@ namespace etl
//*************************************************************************
/// Create from const Lambda or Functor.
//*************************************************************************
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
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)
{
assign((void*)(&instance), const_lambda_stub<TLambda>);
Expand Down
9 changes: 2 additions & 7 deletions include/etl/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,18 +627,13 @@ namespace etl
struct is_base_of
{
private:

template<typename T> struct dummy {};
struct internal: TDerived, dummy<int>{};

static TBase* check(TBase*) { return (TBase*)0; }

template<typename T>
static char check(dummy<T>*) { return 0; }
static char check(...) { return 0; }

public:

static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
static const bool value = (sizeof(check((TDerived*)0)) == sizeof(TBase*));
};

// For when TBase or TDerived is a fundamental type.
Expand Down

0 comments on commit 71b691f

Please sign in to comment.