@@ -38,6 +38,16 @@ template <class T> class VarHolderImpl;
3838}
3939
4040
41+ template <class T , std::size_t S>
42+ struct TypeSizeLE :
43+ std::integral_constant<bool , (sizeof (T) <= S)>{};
44+
45+
46+ template <class T , std::size_t S>
47+ struct TypeSizeGT :
48+ std::integral_constant<bool , (sizeof (T) > S)>{};
49+
50+
4151#ifndef POCO_NO_SOO
4252
4353
@@ -63,11 +73,25 @@ union Placeholder
6373 erase ();
6474 }
6575
76+ void swap (Placeholder& other)
77+ {
78+ if (!isLocal () && !other.isLocal ())
79+ std::swap (pHolder, other.pHolder );
80+ else
81+ throw Poco::InvalidAccessException (" Placeholder::swap()" );
82+ }
83+
6684 void erase ()
6785 {
6886 std::memset (holder, 0 , sizeof (Placeholder));
6987 }
7088
89+ bool isEmpty () const
90+ {
91+ char buf[POCO_SMALL_OBJECT_SIZE] = {};
92+ return 0 == std::memcmp (holder, buf, POCO_SMALL_OBJECT_SIZE);
93+ }
94+
7195 bool isLocal () const
7296 {
7397 return holder[SizeV] != 0 ;
@@ -78,6 +102,22 @@ union Placeholder
78102 holder[SizeV] = local ? 1 : 0 ;
79103 }
80104
105+ template <typename T, typename V>
106+ PlaceholderT* assignStack (const V& value)
107+ {
108+ new (reinterpret_cast <PlaceholderT*>(holder)) T (value);
109+ setLocal (true );
110+ return reinterpret_cast <PlaceholderT*>(holder);
111+ }
112+
113+ template <typename T, typename V>
114+ PlaceholderT* assignHeap (const V& value)
115+ {
116+ pHolder = new T (value);
117+ setLocal (false );
118+ return pHolder;
119+ }
120+
81121 PlaceholderT* content () const
82122 {
83123 if (isLocal ())
@@ -86,20 +126,12 @@ union Placeholder
86126 return pHolder;
87127 }
88128
89- // MSVC71,80 won't extend friendship to nested class (Any::Holder)
90- #if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
91129private:
92- #endif
93- typedef typename std::aligned_storage<SizeV + 1 >::type AlignerType;
94-
95- PlaceholderT* pHolder;
96- mutable char holder[SizeV + 1 ];
97- AlignerType aligner;
130+ typedef typename std::aligned_storage<SizeV+1 >::type AlignerType;
98131
99- friend class Any ;
100- friend class Dynamic ::Var;
101- friend class Dynamic ::VarHolder;
102- template <class > friend class Dynamic ::VarHolderImpl;
132+ PlaceholderT* pHolder;
133+ mutable unsigned char holder[SizeV+1 ];
134+ AlignerType aligner;
103135};
104136
105137
@@ -205,7 +237,7 @@ class Any
205237
206238 if (!_valueHolder.isLocal () && !other._valueHolder .isLocal ())
207239 {
208- std::swap ( _valueHolder.pHolder , other._valueHolder . pHolder );
240+ _valueHolder.swap ( other._valueHolder );
209241 }
210242 else
211243 {
@@ -252,8 +284,7 @@ class Any
252284 bool empty () const
253285 // / Returns true if the Any is empty.
254286 {
255- char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
256- return 0 == std::memcmp (_valueHolder.holder , buf, POCO_SMALL_OBJECT_SIZE);
287+ return _valueHolder.isEmpty ();
257288 }
258289
259290 const std::type_info & type () const
@@ -290,21 +321,27 @@ class Any
290321
291322 virtual void clone (Placeholder<ValueHolder>* pPlaceholder) const
292323 {
293- if ((sizeof (Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
294- {
295- new ((ValueHolder*) pPlaceholder->holder ) Holder (_held);
296- pPlaceholder->setLocal (true );
297- }
298- else
299- {
300- pPlaceholder->pHolder = new Holder (_held);
301- pPlaceholder->setLocal (false );
302- }
324+ cloneSOO (pPlaceholder, _held);
303325 }
304326
305327 ValueType _held;
306328
307329 private:
330+
331+ template <typename VT,
332+ typename std::enable_if<TypeSizeLE<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr >
333+ static void cloneSOO (Placeholder<ValueHolder>* pPlaceholder, VT& held)
334+ {
335+ pPlaceholder->assignStack <Holder<ValueType>, ValueType>(held);
336+ }
337+
338+ template <typename VT,
339+ typename std::enable_if<TypeSizeGT<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr >
340+ static void cloneSOO (Placeholder<ValueHolder>* pPlaceholder, VT& held)
341+ {
342+ pPlaceholder->assignHeap <Holder<ValueType>, ValueType>(held);
343+ }
344+
308345 Holder & operator = (const Holder &);
309346 };
310347
@@ -313,19 +350,18 @@ class Any
313350 return _valueHolder.content ();
314351 }
315352
316- template <typename ValueType>
353+ template <typename ValueType,
354+ typename std::enable_if<TypeSizeLE<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr >
317355 void construct (const ValueType& value)
318356 {
319- if (sizeof (Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
320- {
321- new (reinterpret_cast <ValueHolder*>(_valueHolder.holder )) Holder<ValueType>(value);
322- _valueHolder.setLocal (true );
323- }
324- else
325- {
326- _valueHolder.pHolder = new Holder<ValueType>(value);
327- _valueHolder.setLocal (false );
328- }
357+ _valueHolder.assignStack <Holder<ValueType>, ValueType>(value);
358+ }
359+
360+ template <typename ValueType,
361+ typename std::enable_if<TypeSizeGT<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr >
362+ void construct (const ValueType& value)
363+ {
364+ _valueHolder.assignHeap <Holder<ValueType>, ValueType>(value);
329365 }
330366
331367 void construct (const Any& other)
0 commit comments