From 71b691f7fe3a3da95410f94bc6807d687f356361 Mon Sep 17 00:00:00 2001 From: Vladimir Pinchuk Date: Mon, 21 Oct 2024 10:40:59 +0300 Subject: [PATCH] etl/delegate: fix accident creation of a delegate to an rvalue delegate 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 --- include/etl/private/delegate_cpp03.h | 53 ++++++++++++++++++---------- include/etl/private/delegate_cpp11.h | 45 +++++++++++++++++------ include/etl/type_traits.h | 9 ++--- 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/include/etl/private/delegate_cpp03.h b/include/etl/private/delegate_cpp03.h index 74da0e497..5a1798cb8 100644 --- a/include/etl/private/delegate_cpp03.h +++ b/include/etl/private/delegate_cpp03.h @@ -168,6 +168,23 @@ namespace etl } }; + //***************************************************************** + /// The tag to identify an etl::delegate. + ///\ingroup delegate + //***************************************************************** + struct delegate_tag + { + }; + + //*************************************************************************** + /// is_delegate + //*************************************************************************** + template + struct is_delegate + { + static const bool value = etl::is_base_of::value; + }; + //************************************************************************* /// Declaration. //************************************************************************* @@ -175,10 +192,10 @@ namespace etl class delegate; template - class delegate : public private_delegate::call_if_impl, TReturn, TParam> + class delegate : public private_delegate::call_if_impl, TReturn, TParam>, public delegate_tag { private: - + typedef delegate delegate_type; public: @@ -204,7 +221,7 @@ namespace etl // Construct from a functor. //************************************************************************* template - delegate(TFunctor& instance, typename etl::enable_if::value && !etl::is_same::value, int>::type = 0) + delegate(TFunctor& instance, typename etl::enable_if::value && !is_delegate::value, int>::type = 0) { assign((void*)(&instance), functor_stub); } @@ -213,7 +230,7 @@ namespace etl // Construct from a const functor. //************************************************************************* template - delegate(const TFunctor& instance, typename etl::enable_if::value && !etl::is_same::value, int>::type = 0) + delegate(const TFunctor& instance, typename etl::enable_if::value && !is_delegate::value, int>::type = 0) { assign((void*)(&instance), const_functor_stub); } @@ -232,7 +249,7 @@ namespace etl //************************************************************************* template static - typename etl::enable_if::value &&!etl::is_same::value, delegate>::type + typename etl::enable_if::value &&!is_delegate::value, delegate>::type create(TFunctor& instance) { return delegate((void*)(&instance), functor_stub); @@ -243,7 +260,7 @@ namespace etl //************************************************************************* template static - typename etl::enable_if::value && !etl::is_same::value, delegate>::type + typename etl::enable_if::value && !is_delegate::value, delegate>::type create(const TFunctor& instance) { return delegate((void*)(&instance), const_functor_stub); @@ -330,7 +347,7 @@ namespace etl /// Set from Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, void>::type + typename etl::enable_if::value && !is_delegate::value, void>::type set(TFunctor& instance) { assign((void*)(&instance), functor_stub); @@ -340,7 +357,7 @@ namespace etl /// Set from const Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, void>::type + typename etl::enable_if::value && !is_delegate::value, void>::type set(const TFunctor& instance) { assign((void*)(&instance), const_functor_stub); @@ -467,7 +484,7 @@ namespace etl /// Create from Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, delegate&>::type + typename etl::enable_if::value && !is_delegate::value, delegate&>::type operator =(TFunctor& instance) { assign((void*)(&instance), functor_stub); @@ -478,7 +495,7 @@ namespace etl /// Create from const Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, delegate&>::type + typename etl::enable_if::value && !is_delegate::value, delegate&>::type operator =(const TFunctor& instance) { assign((void*)(&instance), const_functor_stub); @@ -705,7 +722,7 @@ namespace etl // Construct from functor. //************************************************************************* template - delegate(TFunctor& instance, typename etl::enable_if::value && !etl::is_same::value, int>::type = 0) + delegate(TFunctor& instance, typename etl::enable_if::value && !is_delegate::value, int>::type = 0) { assign((void*)(&instance), functor_stub); } @@ -714,7 +731,7 @@ namespace etl // Construct from const functor. //************************************************************************* template - delegate(const TFunctor& instance, typename etl::enable_if::value && !etl::is_same::value, int>::type = 0) + delegate(const TFunctor& instance, typename etl::enable_if::value && !is_delegate::value, int>::type = 0) { assign((void*)(&instance), const_functor_stub); } @@ -733,7 +750,7 @@ namespace etl //************************************************************************* template static - typename etl::enable_if::value && !etl::is_same::value, delegate>::type + typename etl::enable_if::value && !is_delegate::value, delegate>::type create(TFunctor& instance) { return delegate((void*)(&instance), functor_stub); @@ -744,7 +761,7 @@ namespace etl //************************************************************************* template static - typename etl::enable_if::value && !etl::is_same::value, delegate>::type + typename etl::enable_if::value && !is_delegate::value, delegate>::type create(const TFunctor& instance) { return delegate((void*)(&instance), const_functor_stub); @@ -831,7 +848,7 @@ namespace etl /// Set from Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, void>::type + typename etl::enable_if::value && !is_delegate::value, void>::type set(TFunctor& instance) { assign((void*)(&instance), functor_stub); @@ -841,7 +858,7 @@ namespace etl /// Set from const Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, void>::type + typename etl::enable_if::value && !is_delegate::value, void>::type set(const TFunctor& instance) { assign((void*)(&instance), const_functor_stub); @@ -968,7 +985,7 @@ namespace etl /// Create from Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, delegate&>::type + typename etl::enable_if::value && !is_delegate::value, delegate&>::type operator =(TFunctor& instance) { assign((void*)(&instance), functor_stub); @@ -979,7 +996,7 @@ namespace etl /// Create from const Functor. //************************************************************************* template - typename etl::enable_if::value && !etl::is_same::value, delegate&>::type + typename etl::enable_if::value && !is_delegate::value, delegate&>::type operator =(const TFunctor& instance) { assign((void*)(&instance), const_functor_stub); diff --git a/include/etl/private/delegate_cpp11.h b/include/etl/private/delegate_cpp11.h index 8f438602c..1a276bb3b 100644 --- a/include/etl/private/delegate_cpp11.h +++ b/include/etl/private/delegate_cpp11.h @@ -83,16 +83,41 @@ namespace etl } }; + //***************************************************************** + /// The tag to identify an etl::delegate. + ///\ingroup delegate + //***************************************************************** + struct delegate_tag + { + }; + + //*************************************************************************** + /// is_delegate + //*************************************************************************** + template + struct is_delegate + { + static constexpr bool value = etl::is_base_of::value; + }; + +#if ETL_USING_CPP17 + + template + inline constexpr bool is_delegate_v = is_delegate::value; + +#endif + //************************************************************************* /// Declaration. //************************************************************************* - template class delegate; + template + class delegate; //************************************************************************* /// Specialisation. //************************************************************************* template - class delegate final + class delegate final : public delegate_tag { public: @@ -111,7 +136,7 @@ namespace etl //************************************************************************* // Construct from lambda or functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 delegate(TLambda& instance) { assign((void*)(&instance), lambda_stub); @@ -120,7 +145,7 @@ namespace etl //************************************************************************* // Construct from const lambda or functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 delegate(const TLambda& instance) { assign((void*)(&instance), const_lambda_stub); @@ -139,7 +164,7 @@ namespace etl //************************************************************************* /// Create from Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_NODISCARD static ETL_CONSTEXPR14 delegate create(TLambda& instance) { @@ -149,7 +174,7 @@ namespace etl //************************************************************************* /// Create from const Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_NODISCARD static ETL_CONSTEXPR14 delegate create(const TLambda& instance) { @@ -257,7 +282,7 @@ namespace etl //************************************************************************* /// Set from Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 void set(TLambda& instance) { assign((void*)(&instance), lambda_stub); @@ -266,7 +291,7 @@ namespace etl //************************************************************************* /// Set from const Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 void set(const TLambda& instance) { assign((void*)(&instance), const_lambda_stub); @@ -427,7 +452,7 @@ namespace etl //************************************************************************* /// Create from Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 delegate& operator =(TLambda& instance) { assign((void*)(&instance), lambda_stub); @@ -437,7 +462,7 @@ namespace etl //************************************************************************* /// Create from const Lambda or Functor. //************************************************************************* - template ::value && !etl::is_same, TLambda>::value, void>> + template ::value && !is_delegate::value, void>> ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance) { assign((void*)(&instance), const_lambda_stub); diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 47489c2cc..327f164be 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -627,18 +627,13 @@ namespace etl struct is_base_of { private: - - template struct dummy {}; - struct internal: TDerived, dummy{}; - static TBase* check(TBase*) { return (TBase*)0; } - template - static char check(dummy*) { 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.