Skip to content

Commit 71b691f

Browse files
authored
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<T>
1 parent 081e920 commit 71b691f

File tree

3 files changed

+72
-35
lines changed

3 files changed

+72
-35
lines changed

include/etl/private/delegate_cpp03.h

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,17 +168,34 @@ namespace etl
168168
}
169169
};
170170

171+
//*****************************************************************
172+
/// The tag to identify an etl::delegate.
173+
///\ingroup delegate
174+
//*****************************************************************
175+
struct delegate_tag
176+
{
177+
};
178+
179+
//***************************************************************************
180+
/// is_delegate
181+
//***************************************************************************
182+
template <typename T>
183+
struct is_delegate
184+
{
185+
static const bool value = etl::is_base_of<delegate_tag, T>::value;
186+
};
187+
171188
//*************************************************************************
172189
/// Declaration.
173190
//*************************************************************************
174191
template <typename T>
175192
class delegate;
176193

177194
template <typename TReturn, typename TParam>
178-
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>
195+
class delegate<TReturn(TParam)> : public private_delegate::call_if_impl<delegate<TReturn(TParam)>, TReturn, TParam>, public delegate_tag
179196
{
180197
private:
181-
198+
182199
typedef delegate<TReturn(TParam)> delegate_type;
183200

184201
public:
@@ -204,7 +221,7 @@ namespace etl
204221
// Construct from a functor.
205222
//*************************************************************************
206223
template <typename TFunctor>
207-
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
224+
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
208225
{
209226
assign((void*)(&instance), functor_stub<TFunctor>);
210227
}
@@ -213,7 +230,7 @@ namespace etl
213230
// Construct from a const functor.
214231
//*************************************************************************
215232
template <typename TFunctor>
216-
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
233+
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
217234
{
218235
assign((void*)(&instance), const_functor_stub<TFunctor>);
219236
}
@@ -232,7 +249,7 @@ namespace etl
232249
//*************************************************************************
233250
template <typename TFunctor>
234251
static
235-
typename etl::enable_if<etl::is_class<TFunctor>::value &&!etl::is_same<delegate_type, TFunctor>::value, delegate>::type
252+
typename etl::enable_if<etl::is_class<TFunctor>::value &&!is_delegate<TFunctor>::value, delegate>::type
236253
create(TFunctor& instance)
237254
{
238255
return delegate((void*)(&instance), functor_stub<TFunctor>);
@@ -243,7 +260,7 @@ namespace etl
243260
//*************************************************************************
244261
template <typename TFunctor>
245262
static
246-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
263+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
247264
create(const TFunctor& instance)
248265
{
249266
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
@@ -330,7 +347,7 @@ namespace etl
330347
/// Set from Functor.
331348
//*************************************************************************
332349
template <typename TFunctor>
333-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
350+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
334351
set(TFunctor& instance)
335352
{
336353
assign((void*)(&instance), functor_stub<TFunctor>);
@@ -340,7 +357,7 @@ namespace etl
340357
/// Set from const Functor.
341358
//*************************************************************************
342359
template <typename TFunctor>
343-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
360+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
344361
set(const TFunctor& instance)
345362
{
346363
assign((void*)(&instance), const_functor_stub<TFunctor>);
@@ -467,7 +484,7 @@ namespace etl
467484
/// Create from Functor.
468485
//*************************************************************************
469486
template <typename TFunctor>
470-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
487+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
471488
operator =(TFunctor& instance)
472489
{
473490
assign((void*)(&instance), functor_stub<TFunctor>);
@@ -478,7 +495,7 @@ namespace etl
478495
/// Create from const Functor.
479496
//*************************************************************************
480497
template <typename TFunctor>
481-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
498+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
482499
operator =(const TFunctor& instance)
483500
{
484501
assign((void*)(&instance), const_functor_stub<TFunctor>);
@@ -705,7 +722,7 @@ namespace etl
705722
// Construct from functor.
706723
//*************************************************************************
707724
template <typename TFunctor>
708-
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
725+
delegate(TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
709726
{
710727
assign((void*)(&instance), functor_stub<TFunctor>);
711728
}
@@ -714,7 +731,7 @@ namespace etl
714731
// Construct from const functor.
715732
//*************************************************************************
716733
template <typename TFunctor>
717-
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, int>::type = 0)
734+
delegate(const TFunctor& instance, typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, int>::type = 0)
718735
{
719736
assign((void*)(&instance), const_functor_stub<TFunctor>);
720737
}
@@ -733,7 +750,7 @@ namespace etl
733750
//*************************************************************************
734751
template <typename TFunctor>
735752
static
736-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
753+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
737754
create(TFunctor& instance)
738755
{
739756
return delegate((void*)(&instance), functor_stub<TFunctor>);
@@ -744,7 +761,7 @@ namespace etl
744761
//*************************************************************************
745762
template <typename TFunctor>
746763
static
747-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate>::type
764+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate>::type
748765
create(const TFunctor& instance)
749766
{
750767
return delegate((void*)(&instance), const_functor_stub<TFunctor>);
@@ -831,7 +848,7 @@ namespace etl
831848
/// Set from Functor.
832849
//*************************************************************************
833850
template <typename TFunctor>
834-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
851+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
835852
set(TFunctor& instance)
836853
{
837854
assign((void*)(&instance), functor_stub<TFunctor>);
@@ -841,7 +858,7 @@ namespace etl
841858
/// Set from const Functor.
842859
//*************************************************************************
843860
template <typename TFunctor>
844-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, void>::type
861+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, void>::type
845862
set(const TFunctor& instance)
846863
{
847864
assign((void*)(&instance), const_functor_stub<TFunctor>);
@@ -968,7 +985,7 @@ namespace etl
968985
/// Create from Functor.
969986
//*************************************************************************
970987
template <typename TFunctor>
971-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
988+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
972989
operator =(TFunctor& instance)
973990
{
974991
assign((void*)(&instance), functor_stub<TFunctor>);
@@ -979,7 +996,7 @@ namespace etl
979996
/// Create from const Functor.
980997
//*************************************************************************
981998
template <typename TFunctor>
982-
typename etl::enable_if<etl::is_class<TFunctor>::value && !etl::is_same<delegate_type, TFunctor>::value, delegate&>::type
999+
typename etl::enable_if<etl::is_class<TFunctor>::value && !is_delegate<TFunctor>::value, delegate&>::type
9831000
operator =(const TFunctor& instance)
9841001
{
9851002
assign((void*)(&instance), const_functor_stub<TFunctor>);

include/etl/private/delegate_cpp11.h

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,41 @@ namespace etl
8383
}
8484
};
8585

86+
//*****************************************************************
87+
/// The tag to identify an etl::delegate.
88+
///\ingroup delegate
89+
//*****************************************************************
90+
struct delegate_tag
91+
{
92+
};
93+
94+
//***************************************************************************
95+
/// is_delegate
96+
//***************************************************************************
97+
template <typename T>
98+
struct is_delegate
99+
{
100+
static constexpr bool value = etl::is_base_of<delegate_tag, T>::value;
101+
};
102+
103+
#if ETL_USING_CPP17
104+
105+
template <typename T>
106+
inline constexpr bool is_delegate_v = is_delegate<T>::value;
107+
108+
#endif
109+
86110
//*************************************************************************
87111
/// Declaration.
88112
//*************************************************************************
89-
template <typename T> class delegate;
113+
template <typename T>
114+
class delegate;
90115

91116
//*************************************************************************
92117
/// Specialisation.
93118
//*************************************************************************
94119
template <typename TReturn, typename... TParams>
95-
class delegate<TReturn(TParams...)> final
120+
class delegate<TReturn(TParams...)> final : public delegate_tag
96121
{
97122
public:
98123

@@ -111,7 +136,7 @@ namespace etl
111136
//*************************************************************************
112137
// Construct from lambda or functor.
113138
//*************************************************************************
114-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
139+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
115140
ETL_CONSTEXPR14 delegate(TLambda& instance)
116141
{
117142
assign((void*)(&instance), lambda_stub<TLambda>);
@@ -120,7 +145,7 @@ namespace etl
120145
//*************************************************************************
121146
// Construct from const lambda or functor.
122147
//*************************************************************************
123-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
148+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
124149
ETL_CONSTEXPR14 delegate(const TLambda& instance)
125150
{
126151
assign((void*)(&instance), const_lambda_stub<TLambda>);
@@ -139,7 +164,7 @@ namespace etl
139164
//*************************************************************************
140165
/// Create from Lambda or Functor.
141166
//*************************************************************************
142-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
167+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
143168
ETL_NODISCARD
144169
static ETL_CONSTEXPR14 delegate create(TLambda& instance)
145170
{
@@ -149,7 +174,7 @@ namespace etl
149174
//*************************************************************************
150175
/// Create from const Lambda or Functor.
151176
//*************************************************************************
152-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
177+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
153178
ETL_NODISCARD
154179
static ETL_CONSTEXPR14 delegate create(const TLambda& instance)
155180
{
@@ -257,7 +282,7 @@ namespace etl
257282
//*************************************************************************
258283
/// Set from Lambda or Functor.
259284
//*************************************************************************
260-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
285+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
261286
ETL_CONSTEXPR14 void set(TLambda& instance)
262287
{
263288
assign((void*)(&instance), lambda_stub<TLambda>);
@@ -266,7 +291,7 @@ namespace etl
266291
//*************************************************************************
267292
/// Set from const Lambda or Functor.
268293
//*************************************************************************
269-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
294+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
270295
ETL_CONSTEXPR14 void set(const TLambda& instance)
271296
{
272297
assign((void*)(&instance), const_lambda_stub<TLambda>);
@@ -427,7 +452,7 @@ namespace etl
427452
//*************************************************************************
428453
/// Create from Lambda or Functor.
429454
//*************************************************************************
430-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
455+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
431456
ETL_CONSTEXPR14 delegate& operator =(TLambda& instance)
432457
{
433458
assign((void*)(&instance), lambda_stub<TLambda>);
@@ -437,7 +462,7 @@ namespace etl
437462
//*************************************************************************
438463
/// Create from const Lambda or Functor.
439464
//*************************************************************************
440-
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !etl::is_same<etl::delegate<TReturn(TParams...)>, TLambda>::value, void>>
465+
template <typename TLambda, typename = etl::enable_if_t<etl::is_class<TLambda>::value && !is_delegate<TLambda>::value, void>>
441466
ETL_CONSTEXPR14 delegate& operator =(const TLambda& instance)
442467
{
443468
assign((void*)(&instance), const_lambda_stub<TLambda>);

include/etl/type_traits.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -627,18 +627,13 @@ namespace etl
627627
struct is_base_of
628628
{
629629
private:
630-
631-
template<typename T> struct dummy {};
632-
struct internal: TDerived, dummy<int>{};
633-
634630
static TBase* check(TBase*) { return (TBase*)0; }
635631

636-
template<typename T>
637-
static char check(dummy<T>*) { return 0; }
632+
static char check(...) { return 0; }
638633

639634
public:
640635

641-
static const bool value = (sizeof(check((internal*)0)) == sizeof(TBase*));
636+
static const bool value = (sizeof(check((TDerived*)0)) == sizeof(TBase*));
642637
};
643638

644639
// For when TBase or TDerived is a fundamental type.

0 commit comments

Comments
 (0)