[Tizen] Add assertion to Vector
[platform/core/uifw/dali-core.git] / dali / public-api / common / dali-vector.h
1 #ifndef DALI_VECTOR_H
2 #define DALI_VECTOR_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <assert.h>
23 #include <algorithm>
24 #include <cstddef>
25 #include <cstdint> // uint32_t
26
27 // INTERNAL INCLUDES
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/type-traits.h>
30 #include <dali/public-api/math/math-utils.h>
31
32 #define DALI_ASSERT_VECTOR(cond) DALI_ASSERT_ALWAYS(cond)
33
34 namespace Dali
35 {
36 /**
37  * @addtogroup dali_core_common
38  * @{
39  */
40
41 /**
42  * @brief Base class to handle the memory of simple vector.
43  *
44  * Memory layout is such that it has two std::size_t to hold the count
45  * and capacity of the vector. VectorBase::mData is adjusted so that it points to the
46  * beginning of the first real item so that iterating the items is quick.
47  * @SINCE_1_0.0
48  */
49 class DALI_CORE_API VectorBase
50 {
51 public: // Typedefs
52   using SizeType = std::size_t;
53
54 protected: // Construction
55   /**
56    * @brief Default constructor. Does not allocate space.
57    * @SINCE_1_0.0
58    */
59   VectorBase();
60
61   /**
62    * @brief Destructor.
63    *
64    * Does not release the space. Derived class needs to call Release.
65    * Not virtual as this should not be called directly and we do not want
66    * a vtable for this class as it would unnecessarily increase size.
67    * @SINCE_1_0.0
68    */
69   ~VectorBase();
70
71 public: // API
72   /**
73    * @brief This method is inlined as it's needed frequently for Vector::End() iterator.
74    *
75    * @SINCE_1_0.0
76    * @return The count of elements in this vector
77    */
78   SizeType Count() const
79   {
80     SizeType items = 0u;
81     if(mData)
82     {
83       SizeType* metadata = reinterpret_cast<SizeType*>(mData);
84       items              = *(metadata - 1u);
85     }
86     return items;
87   }
88
89   /**
90    * @brief Gets the count of elements in this vector.
91    * @SINCE_1_0.0
92    * @return The count of elements in this vector
93    */
94   SizeType Size() const
95   {
96     return Count();
97   }
98
99   /**
100    * @brief @ return if the vector is empty.
101    * @SINCE_1_0.0
102    * @return True if the count of elements is empty
103    */
104   bool Empty() const
105   {
106     return Count() == 0u;
107   }
108
109   /**
110    * @brief Gets the capacity of this vector.
111    * @SINCE_1_0.0
112    * @return The capacity of this vector
113    */
114   SizeType Capacity() const;
115
116   /**
117    * @brief Releases the data.
118    *
119    * Does not call destructors on objects held.
120    * @SINCE_1_0.0
121    */
122   void Release();
123
124 protected: // for Derived classes
125   /**
126    * @brief Helper to set the count.
127    *
128    * @SINCE_1_0.0
129    * @param[in] count Number of elements in the vector
130    */
131   void SetCount(SizeType count);
132
133   /**
134    * @brief Reserves space in the vector.
135    *
136    * @SINCE_1_0.0
137    * @param[in] count Count of elements to reserve
138    * @param[in] elementSize Size of a single element
139    */
140   void Reserve(SizeType count, SizeType elementSize);
141
142   /**
143    * @brief Copy a vector.
144    *
145    * @SINCE_1_0.0
146    * @param[in] vector Vector to copy from
147    * @param[in] elementSize Size of a single element
148    */
149   void Copy(const VectorBase& vector, SizeType elementSize);
150
151   /**
152    * @brief Swaps the contents of two vectors.
153    *
154    * @SINCE_1_0.0
155    * @param[in] vector Vector to swap with
156    */
157   void Swap(VectorBase& vector);
158
159   /**
160    * @brief Erases an element.
161    *
162    * Does not change capacity.
163    * @SINCE_1_0.0
164    * @param[in] address Address to erase from
165    * @param[in] elementSize Size to erase
166    * @pre Last element cannot be erased as there is nothing to move.
167    */
168   void Erase(char* address, SizeType elementSize);
169
170   /**
171    * @brief Erases a range of elements.
172    *
173    * Does not change capacity.
174    * @SINCE_1_0.0
175    * @param[in] first Address to the first element to be erased
176    * @param[in] last Address to the last element to be erased
177    * @param[in] elementSize Size of one of the elements to be erased
178    * @return Address pointing to the next element of the last one
179    */
180   char* Erase(char* first, char* last, SizeType elementSize);
181
182   /**
183    * @brief Copies a number of bytes from \e source to \e destination.
184    *
185    * \e source and \e destination must not overlap.
186    *
187    * @SINCE_1_0.0
188    * @param[in] destination Pointer to the destination address
189    * @param[in] source Pointer to the source address
190    * @param[in] numberOfBytes The number of bytes to be copied
191    */
192   void CopyMemory(char* destination, const char* source, size_t numberOfBytes);
193
194 private:
195   // not copyable as it does not know the size of elements
196   VectorBase(const VectorBase&) = delete;            ///< Deleted copy constructor. @SINCE_1_0.0
197   VectorBase& operator=(const VectorBase&) = delete; ///< Deleted copy assignment operator. @SINCE_1_0.0
198
199   // not movable as this is handled by deriving classes
200   VectorBase(VectorBase&&) = delete;            ///< Deleted move constructor. @SINCE_1_9.25
201   VectorBase& operator=(VectorBase&&) = delete; ///< Deleted copy assignment operator. @SINCE_1_9.25
202
203 protected:     // Data
204   void* mData; ///< Pointer to the data.
205 };
206
207 /// @cond internal
208 /**
209  * @brief Vector algorithm variant for trivial types.
210  *
211  * Trivial types do not need destructor or copy constructor called.
212  * @SINCE_1_0.0
213  */
214 template<bool IsTrivial>
215 class VectorAlgorithms : public VectorBase
216 {
217 protected: // API for deriving classes
218   using SizeType = VectorBase::SizeType;
219
220   /**
221    * @brief Empty constructor.
222    * @SINCE_1_0.0
223    */
224   VectorAlgorithms() = default;
225
226   /**
227    * @brief Empty destructor.
228    * @SINCE_1_0.0
229    */
230   ~VectorAlgorithms() = default;
231
232   /**
233    * @brief Copy vector contents.
234    *
235    * @SINCE_1_0.0
236    * @param[in] rhs VectorBase object to copy from
237    * @param[in] elementSize Size of the content
238    */
239   void Copy(const VectorBase& rhs, SizeType elementSize)
240   {
241     if(rhs.Capacity() > 0u)
242     {
243       VectorBase::Copy(rhs, elementSize);
244     }
245     else
246     {
247       VectorBase::Release();
248     }
249   }
250
251   /**
252    * @brief Reserves space in the vector.
253    *
254    * @SINCE_1_0.0
255    * @param[in] count Count of elements to reserve
256    * @param[in] elementSize Size of a single element
257    */
258   void Reserve(SizeType count, SizeType elementSize)
259   {
260     VectorBase::Reserve(count, elementSize);
261   }
262
263   /**
264    * @brief Resizes the vector. Does not change capacity.
265    *
266    * @SINCE_1_0.0
267    * @param[in] count Count to resize to
268    * @param[in] elementSize Size of a single element
269    */
270   void Resize(SizeType count, SizeType elementSize)
271   {
272     // reserve will copy old elements as well
273     Reserve(count, elementSize);
274   }
275
276   /**
277    * @brief Clears the contents.
278    *
279    * For simple types, nothing to do.
280    * @SINCE_1_0.0
281    */
282   void Clear()
283   {
284     if(mData)
285     {
286       VectorBase::SetCount(0u);
287     }
288   }
289
290   /**
291    * @brief Releases the vector.
292    * @SINCE_1_0.0
293    */
294   void Release()
295   {
296     VectorBase::Release();
297   }
298
299   /**
300    * @brief Erases an element. Does not change capacity.
301    *
302    * @SINCE_1_0.0
303    * @param[in] address Address to erase from
304    * @param[in] elementSize Size to erase
305    */
306   void Erase(uint8_t* address, SizeType elementSize)
307   {
308     VectorBase::Erase(reinterpret_cast<char*>(address), elementSize);
309   }
310
311   /**
312    * @brief Erases a range of elements. Does not change capacity.
313    *
314    * @SINCE_1_0.0
315    * @param[in] first Address to the first element to be erased
316    * @param[in] last Address to the last element to be erased
317    * @param[in] elementSize Size of one of the elements to be erased
318    * @return Address pointing to the next element of the last one
319    */
320   uint8_t* Erase(uint8_t* first, uint8_t* last, SizeType elementSize)
321   {
322     return reinterpret_cast<uint8_t*>(VectorBase::Erase(reinterpret_cast<char*>(first), reinterpret_cast<char*>(last), elementSize));
323   }
324
325   /**
326    * @brief Inserts the given elements into the vector.
327    *
328    * @SINCE_1_0.0
329    * @param[in] at Address where to insert the elements into the vector
330    * @param[in] from Address to the first element to be inserted
331    * @param[in] to Address to the last element to be inserted
332    * @param[in] elementSize Size of one of the elements to be inserted
333    */
334   void Insert(uint8_t* at, uint8_t* from, uint8_t* to, SizeType elementSize)
335   {
336     const SizeType size     = to - from;
337     const SizeType count    = Count();
338     const SizeType newCount = count + size / elementSize;
339
340     if(newCount > Capacity())
341     {
342       // Calculate the at offset as the pointer is invalid after the Reserve() call.
343       std::size_t offset = at - reinterpret_cast<uint8_t*>(mData);
344
345       // need more space
346       Reserve(NextPowerOfTwo(static_cast<uint32_t>(newCount)), elementSize); // reserve enough space to store at least the next power of two elements of the new required size.
347
348       // Set the new at pointer.
349       at = reinterpret_cast<uint8_t*>(mData) + offset;
350     }
351     // set new count first as otherwise the debug assert will hit us
352     SetCount(newCount);
353
354     // Move current items to a new position inside the vector.
355     CopyMemory(reinterpret_cast<char*>(at + size),
356                reinterpret_cast<const char*>(at),
357                (reinterpret_cast<uint8_t*>(mData) + count * elementSize) - at);
358
359     // Copy the given items.
360     CopyMemory(reinterpret_cast<char*>(at), reinterpret_cast<const char*>(from), size);
361   }
362 };
363 /// @endcond
364
365 /// @cond internal
366 /**
367  * @brief Vector algorithm variant for complex types.
368  *
369  * Not yet supported so will lead to compile error
370  * as constructor and destructor are private.
371  * TODO add support for this variant.
372  * @SINCE_1_0.0
373  */
374 template<>
375 class VectorAlgorithms<false> : public VectorBase
376 {
377 private:
378   VectorAlgorithms()  = default;
379   ~VectorAlgorithms() = default;
380 };
381 /// @endcond
382
383 /**
384  * @brief Vector class with minimum space allocation when it's empty.
385  *
386  * @SINCE_1_0.0
387  * @param type The type of the data that the vector holds
388  */
389 template<class T, bool IsTrivialType = TypeTraits<T>::IS_TRIVIAL_TYPE == true>
390 class Vector : public VectorAlgorithms<IsTrivialType>
391 {
392 public: // API
393   /**
394    * @brief Type definitions.
395    * @SINCE_1_0.0
396    */
397   using SizeType      = VectorBase::SizeType; ///< Size type @SINCE_1_0.0
398   using Iterator      = T*;                   ///< Most simple Iterator is a pointer @SINCE_1_0.0
399   using ConstIterator = const T*;             ///< Const iterator @SINCE_1_0.0
400   using ItemType      = T;                    ///< Item type @SINCE_1_0.0
401
402   /**
403    * @brief Enumeration for BaseType.
404    * @SINCE_1_0.0
405    */
406   enum
407   {
408     BaseType = IsTrivialType ///< @SINCE_1_0.0
409   };
410
411   /**
412    * @brief Default constructor. Does not allocate any space.
413    * @SINCE_1_0.0
414    */
415   Vector() = default;
416
417   /**
418    * @brief Destructor. Releases the allocated space.
419    * @SINCE_1_0.0
420    */
421   ~Vector()
422   {
423     Release();
424   }
425
426   /**
427    * @brief Copy constructor.
428    *
429    * @SINCE_1_0.0
430    * @param[in] vector Vector to copy from
431    */
432   Vector(const Vector& vector)
433   {
434     // reuse copy assignment
435     operator=(vector);
436   }
437
438   /**
439    * @brief Default move constructor.
440    *
441    * @SINCE_1_9.25
442    * @param[in] vector Vector to move
443    */
444   Vector(Vector&& vector)
445   {
446     // reuse move assignment
447     operator=(std::move(vector));
448   }
449
450   /**
451    * @brief Assignment operator.
452    *
453    * @SINCE_1_0.0
454    * @param[in] vector Vector to assign from
455    * @return Reference to self for chaining
456    */
457   Vector& operator=(const Vector& vector)
458   {
459     if(this != &vector)
460     {
461       VectorAlgorithms<BaseType>::Copy(vector, sizeof(ItemType));
462     }
463     return *this;
464   }
465
466   /**
467    * @brief Default move assignment operator.
468    *
469    * @SINCE_1_9.25
470    * @param[in] vector Vector to move
471    */
472   Vector& operator=(Vector&& vector)
473   {
474     if(this != &vector)
475     {
476       if(VectorBase::mData)
477       {
478         Release();
479       }
480       VectorBase::mData = vector.mData;
481       vector.mData      = nullptr;
482     }
483     return *this;
484   }
485
486   /**
487    * @brief Iterator to the beginning of the data.
488    * @SINCE_1_0.0
489    * @return Iterator to the beginning of the data
490    */
491   Iterator Begin() const
492   {
493     ItemType* address = reinterpret_cast<ItemType*>(VectorBase::mData);
494     return address;
495   }
496
497   /**
498    * @brief Iterator to the end of the data (one past last element).
499    * @SINCE_1_0.0
500    * @return Iterator to the end of the data (one past last element)
501    */
502   Iterator End() const
503   {
504     ItemType* address = reinterpret_cast<ItemType*>(VectorBase::mData);
505     address += VectorBase::Count();
506     return address;
507   }
508
509   /**
510    * Support for C++11 Range-based for loop: for( item : container ).
511    * @SINCE_1_2.60
512    * @return The start iterator
513    */
514   Iterator begin() const
515   {
516     return Begin();
517   }
518
519   /**
520    * Support for C++11 Range-based for loop: for( item : container ).
521    * @SINCE_1_2.60
522    * @return The end iterator
523    */
524   Iterator end() const
525   {
526     return End();
527   }
528
529   /**
530    * @brief Subscript operator.
531    * @SINCE_1_0.0
532    * @param[in] index Index of the element
533    * @return Reference to the element for given index
534    * @pre Index must be in the vector's range.
535    */
536   ItemType& operator[](SizeType index)
537   {
538     // reuse the const version
539     return const_cast<ItemType&>(const_cast<const Vector<ItemType>&>(*this)[index]);
540   }
541
542   /**
543    * @brief Subscript operator.
544    * @SINCE_1_0.0
545    * @param[in] index Index of the element
546    * @return Reference to the element for given index
547    * @pre Index must be in the vector's range.
548    */
549   const ItemType& operator[](SizeType index) const
550   {
551     DALI_ASSERT_VECTOR(VectorBase::mData && "Vector is empty");
552     assert(index < VectorBase::Count());
553
554     ItemType* address = reinterpret_cast<ItemType*>(VectorBase::mData);
555     address += index;
556     return *address;
557   }
558
559   /**
560    * @brief Pushes back an element to the vector.
561    *
562    * The underlying storage may be reallocated to provide space.
563    * If this occurs, all pre-existing pointers into the vector will
564    * become invalid.
565    *
566    * @SINCE_1_0.0
567    * @param[in] element Element to be added
568    */
569   void PushBack(const ItemType& element)
570   {
571     const SizeType count    = VectorBase::Count();
572     const SizeType newCount = count + 1u;
573     const SizeType capacity = VectorBase::Capacity();
574     if(newCount > capacity)
575     {
576       // need more space
577       Reserve(newCount << 1u); // reserve double the current count
578     }
579     // set new count first as otherwise the debug assert will hit us
580     VectorBase::SetCount(newCount);
581     operator[](count) = element;
582   }
583
584   /**
585    * @brief Inserts an element to the vector.
586    *
587    * Elements after \e at are moved one position to the right.
588    *
589    * The underlying storage may be reallocated to provide space.
590    * If this occurs, all pre-existing pointers into the vector will
591    * become invalid.
592    *
593    * @SINCE_1_0.0
594    * @param[in] at Iterator where to insert the elements into the vector
595    * @param[in] element An element to be added
596    * @pre Iterator at must be in the vector's range ( Vector::Begin(), Vector::End() ).
597    */
598   void Insert(Iterator at, const ItemType& element)
599   {
600     DALI_ASSERT_VECTOR((at <= End()) && (at >= Begin()) && "Iterator not inside vector");
601     const SizeType size    = sizeof(ItemType);
602     uint8_t*       address = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&element));
603     VectorAlgorithms<BaseType>::Insert(reinterpret_cast<uint8_t*>(at),
604                                        address,
605                                        address + size,
606                                        size);
607   }
608
609   /**
610    * @brief Inserts the given elements into the vector.
611    *
612    * Elements after \e at are moved the number of given elements positions to the right.
613    *
614    * The underlying storage may be reallocated to provide space.
615    * If this occurs, all pre-existing pointers into the vector will
616    * become invalid.
617    *
618    * @SINCE_1_0.0
619    * @param[in] at Iterator where to insert the elements into the vector
620    * @param[in] from Iterator to the first element to be inserted
621    * @param[in] to Iterator to the last element to be inserted
622    * @pre Iterator \e at must be in the vector's range ( Vector::Begin(), Vector::End() ).
623    * @pre Iterators \e from and \e to must be valid iterators.
624    * @pre Iterator \e from must not be grater than Iterator \e to.
625    *
626    */
627   void Insert(Iterator at, Iterator from, Iterator to)
628   {
629     DALI_ASSERT_VECTOR((at <= End()) && (at >= Begin()) && "Iterator not inside vector");
630     DALI_ASSERT_VECTOR((from <= to) && "from address can't be greater than to");
631
632     if(from == to)
633     {
634       // nothing to copy.
635       return;
636     }
637
638     VectorAlgorithms<BaseType>::Insert(reinterpret_cast<uint8_t*>(at),
639                                        reinterpret_cast<uint8_t*>(from),
640                                        reinterpret_cast<uint8_t*>(to),
641                                        sizeof(ItemType));
642   }
643
644   /**
645    * @brief Reserves space in the vector.
646    *
647    * Reserving less than current Capacity is a no-op.
648    * @SINCE_1_0.0
649    * @param[in] count Count of elements to reserve
650    */
651   void Reserve(SizeType count)
652   {
653     VectorAlgorithms<BaseType>::Reserve(count, sizeof(ItemType));
654   }
655
656   /**
657    * @brief Resizes the vector. Does not change capacity.
658    *
659    * @SINCE_1_0.0
660    * @param[in] count Count to resize to
661    */
662   void Resize(SizeType count)
663   {
664     ItemType item = ItemType();
665     Resize(count, item);
666   }
667
668   /**
669    * @brief Resizes the vector without initializing the data.
670    *
671    * Can be used as a data container for reading whole file content.
672    * @SINCE_1_9.27
673    * @param[in] count Count to resize to
674    */
675   void ResizeUninitialized(SizeType count)
676   {
677     Reserve(count);
678     VectorBase::SetCount(count);
679   }
680
681   /**
682    * @brief Resizes the vector. Does not change capacity.
683    *
684    * @SINCE_1_0.0
685    * @param[in] count Count to resize to
686    * @param[in] item An item to insert to the new indices
687    */
688   void Resize(SizeType count, const ItemType& item)
689   {
690     const SizeType oldCount = VectorBase::Count();
691     if(count <= oldCount)
692     {
693       // getting smaller so just set count
694       VectorBase::SetCount(count);
695     }
696     else
697     {
698       // remember how many new items get added
699       SizeType newItems = count - oldCount;
700       Reserve(count);
701       for(; newItems > 0u; --newItems)
702       {
703         PushBack(item);
704       }
705     }
706   }
707
708   /**
709    * @brief Erases an element.
710    *
711    * Does not change capacity. Other elements get moved.
712    *
713    * @SINCE_1_0.0
714    * @param[in] iterator Iterator pointing to the item to remove
715    * @return Iterator pointing to next element
716    * @pre Iterator \e iterator must be within the vector's range ( Vector::Begin(), Vector::End() - 1 ).
717    *
718    */
719   Iterator Erase(Iterator iterator)
720   {
721     DALI_ASSERT_VECTOR((iterator < End()) && (iterator >= Begin()) && "Iterator not inside vector");
722     if(iterator < (End() - 1u))
723     {
724       VectorAlgorithms<BaseType>::Erase(reinterpret_cast<uint8_t*>(iterator), sizeof(ItemType));
725     }
726     else
727     {
728       // just remove the element
729       Remove(iterator);
730     }
731     return iterator;
732   }
733
734   /**
735    * @brief Erases a range of elements.
736    *
737    * Does not change capacity. Other elements get moved.
738    *
739    * @SINCE_1_0.0
740    * @param[in] first Iterator to the first element to be erased
741    * @param[in] last Iterator to the last element to be erased
742    *
743    * @return Iterator pointing to the next element of the last one
744    * @pre Iterator \e first must be in the vector's range ( Vector::Begin(), Vector::End() ).
745    * @pre Iterator \e last must be in the vector's range ( Vector::Begin(), Vector::End() ).
746    * @pre Iterator \e first must not be grater than Iterator \e last.
747    *
748    */
749   Iterator Erase(Iterator first, Iterator last)
750   {
751     DALI_ASSERT_VECTOR((first <= End()) && (first >= Begin()) && "Iterator not inside vector");
752     DALI_ASSERT_VECTOR((last <= End()) && (last >= Begin()) && "Iterator not inside vector");
753     DALI_ASSERT_VECTOR((first <= last) && "first iterator greater than last");
754
755     Iterator nextElement;
756
757     if(last == End())
758     {
759       // Erase up to the end.
760       VectorBase::SetCount(VectorBase::Count() - (last - first));
761       nextElement = End();
762     }
763     else
764     {
765       nextElement = reinterpret_cast<Iterator>(VectorAlgorithms<BaseType>::Erase(reinterpret_cast<uint8_t*>(first),
766                                                                                  reinterpret_cast<uint8_t*>(last),
767                                                                                  sizeof(ItemType)));
768     }
769
770     return nextElement;
771   }
772
773   /**
774    * @brief Removes an element.
775    *
776    * Does not maintain order. Swaps the element with end and
777    * decreases size by one.  This is much faster than Erase so use
778    * this in case order does not matter. Does not change capacity.
779    *
780    * @SINCE_1_0.0
781    * @param[in] iterator Iterator pointing to the item to remove
782    * @pre Iterator \e iterator must be in the vector's range ( Vector::Begin(), Vector::End() - 1 ).
783    *
784    */
785   void Remove(Iterator iterator)
786   {
787     DALI_ASSERT_VECTOR((iterator < End()) && (iterator >= Begin()) && "Iterator not inside vector");
788
789     Iterator last = End() - 1u;
790     if(last > iterator)
791     {
792       std::swap(*iterator, *last);
793     }
794     VectorBase::SetCount(VectorBase::Count() - 1u);
795   }
796
797   /**
798    * @brief Swaps the contents of two vectors.
799    *
800    * @SINCE_1_0.0
801    * @param[in] vector Vector to swap with
802    */
803   void Swap(Vector& vector)
804   {
805     VectorBase::Swap(vector);
806   }
807
808   /**
809    * @brief Clears the contents of the vector. Keeps its capacity.
810    * @SINCE_1_0.0
811    */
812   void Clear()
813   {
814     VectorAlgorithms<BaseType>::Clear();
815   }
816
817   /**
818    * @brief Releases the memory that the vector holds.
819    * @SINCE_1_0.0
820    */
821   void Release()
822   {
823     VectorAlgorithms<BaseType>::Release();
824   }
825 };
826
827 /**
828  * @brief Erases all elements that compare equal to value from the vector.
829  *
830  * @SINCE_1_9.33
831  * @param[in] vector The vector
832  * @param[in] value The value to be removed.
833  */
834 template<class T, class U>
835 inline void Erase(Dali::Vector<T>& vector, const U& value)
836 {
837   auto begin = vector.Begin();
838   auto end   = vector.End();
839
840   vector.Erase(std::remove(begin, end, value), end);
841 }
842
843 /**
844  * @brief Erases all elements that satisfy the predicate from the vector.
845  *
846  * @SINCE_1_9.33
847  * @param[in] vector The vector
848  * @param[in] predicate The predicate
849  */
850 template<class T, class Predicate>
851 inline void EraseIf(Dali::Vector<T>& vector, Predicate predicate)
852 {
853   auto begin = vector.Begin();
854   auto end   = vector.End();
855
856   vector.Erase(std::remove_if(begin, end, predicate), end);
857 }
858
859 /**
860  * @}
861  */
862 } // namespace Dali
863
864 #endif // DALI_VECTOR_H