1919
2020#include " iox/vector.hpp"
2121
22+ #include < cstring> // std::memcpy, std::memmove
2223#include < iostream>
24+ #include < type_traits>
2325
2426namespace iox
2527{
@@ -52,10 +54,14 @@ inline vector<T, Capacity>::vector(const uint64_t count) noexcept
5254 }
5355
5456 m_size = std::min (count, Capacity);
55- for (uint64_t i{0U }; i < m_size; ++i)
57+ // If the type is a trivial class without member initialization the constructor would not initialize the data
58+ if constexpr (!(std::is_trivial<T>::value && std::is_class<T>::value))
5659 {
57- // AXIVION Next Line AutosarC++19_03-A18.5.2, FaultDetection-IndirectAssignmentOverflow : False positive, it is a placement new. Size guaranteed by T.
58- new (&at (i)) T ();
60+ for (uint64_t i{0U }; i < m_size; ++i)
61+ {
62+ // AXIVION Next Line AutosarC++19_03-A18.5.2, FaultDetection-IndirectAssignmentOverflow : False positive, it is a placement new. Size guaranteed by T.
63+ new (&at_unchecked (i)) T ();
64+ }
5965 }
6066}
6167
@@ -84,19 +90,28 @@ inline vector<T, Capacity>& vector<T, Capacity>::operator=(const vector& rhs) no
8490 {
8591 uint64_t i{0U };
8692 const uint64_t rhsSize{rhs.size ()};
87- const uint64_t minSize{algorithm::minVal (m_size, rhsSize)};
8893
89- // copy using copy assignment
90- for (; i < minSize; ++i)
94+ if constexpr (std::is_trivially_copyable<T>::value)
9195 {
92- // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
93- at (i) = rhs. at (i) ;
96+ std::memcpy ( data (), rhs. data (), rhsSize * sizeof (T));
97+ i = rhsSize ;
9498 }
95-
96- // copy using copy ctor
97- for (; i < rhsSize; ++i)
99+ else
98100 {
99- IOX_DISCARD_RESULT (emplace_back (rhs.at (i)));
101+ const uint64_t minSize{algorithm::minVal (m_size, rhsSize)};
102+
103+ // copy using copy assignment
104+ for (; i < minSize; ++i)
105+ {
106+ // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
107+ at (i) = rhs.at (i);
108+ }
109+
110+ // copy using copy ctor
111+ for (; i < rhsSize; ++i)
112+ {
113+ IOX_DISCARD_RESULT (emplace_back (rhs.at (i)));
114+ }
100115 }
101116
102117 // delete remaining elements
@@ -114,19 +129,28 @@ inline vector<T, Capacity>& vector<T, Capacity>::operator=(vector&& rhs) noexcep
114129 {
115130 uint64_t i{0U };
116131 const uint64_t rhsSize{rhs.size ()};
117- const uint64_t minSize{algorithm::minVal (m_size, rhsSize)};
118132
119- // move using move assignment
120- for (; i < minSize; ++i)
133+ if constexpr (std::is_trivially_copyable<T>::value)
121134 {
122- // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
123- at (i) = std::move (rhs. at (i)) ;
135+ std::memcpy ( data (), rhs. data (), rhsSize * sizeof (T));
136+ i = rhsSize ;
124137 }
125-
126- // move using move ctor
127- for (; i < rhsSize; ++i)
138+ else
128139 {
129- IOX_DISCARD_RESULT (emplace_back (std::move (rhs.at (i))));
140+ const uint64_t minSize{algorithm::minVal (m_size, rhsSize)};
141+
142+ // move using move assignment
143+ for (; i < minSize; ++i)
144+ {
145+ // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
146+ at (i) = std::move (rhs.at (i));
147+ }
148+
149+ // move using move ctor
150+ for (; i < rhsSize; ++i)
151+ {
152+ IOX_DISCARD_RESULT (emplace_back (std::move (rhs.at (i))));
153+ }
130154 }
131155
132156 // delete remaining elements
@@ -168,8 +192,15 @@ inline bool vector<T, Capacity>::emplace_back(Targs&&... args) noexcept
168192{
169193 if (m_size < Capacity)
170194 {
171- // AXIVION Next Line AutosarC++19_03-A5.0.1, FaultDetection-IndirectAssignmentOverflow: Size guaranteed by T. Evaluation order is inconsequential.
172- new (&at (m_size++)) T (std::forward<Targs>(args)...);
195+ if constexpr (std::is_trivial<T>::value)
196+ {
197+ at_unchecked (m_size++) = T{std::forward<Targs>(args)...};
198+ }
199+ else
200+ {
201+ // AXIVION Next Line AutosarC++19_03-A5.0.1, FaultDetection-IndirectAssignmentOverflow: Size guaranteed by T. Evaluation order is inconsequential.
202+ new (&at_unchecked (m_size++)) T{std::forward<Targs>(args)...};
203+ }
173204 return true ;
174205 }
175206 return false ;
@@ -189,14 +220,26 @@ inline bool vector<T, Capacity>::emplace(const uint64_t position, Targs&&... arg
189220 {
190221 return emplace_back (std::forward<Targs>(args)...);
191222 }
192- IOX_DISCARD_RESULT (emplace_back (std::move (at_unchecked (sizeBeforeEmplace - 1U ))));
193- for (uint64_t i{sizeBeforeEmplace - 1U }; i > position; --i)
223+ if constexpr (std::is_trivial<T>::value)
194224 {
195- at_unchecked (i) = std::move (at_unchecked (i - 1U ));
225+ resize (size () + 1U );
226+ const uint64_t dataLen{sizeBeforeEmplace - position};
227+ std::memmove (data () + position + 1U , data () + position, dataLen * sizeof (T));
228+ at_unchecked (position) = T{std::forward<Targs>(args)...};
229+ }
230+ else
231+ {
232+ IOX_DISCARD_RESULT (emplace_back (std::move (at_unchecked (sizeBeforeEmplace - 1U ))));
233+ for (uint64_t i{sizeBeforeEmplace - 1U }; i > position; --i)
234+ {
235+ at_unchecked (i) = std::move (at_unchecked (i - 1U ));
236+ }
237+ if constexpr (!std::is_trivially_destructible<T>::value)
238+ {
239+ at_unchecked (position).~T ();
240+ }
241+ new (&at_unchecked (position)) T (std::forward<Targs>(args)...);
196242 }
197-
198- at (position).~T ();
199- new (&at (position)) T (std::forward<Targs>(args)...);
200243 return true ;
201244}
202245
@@ -218,7 +261,14 @@ inline bool vector<T, Capacity>::pop_back() noexcept
218261{
219262 if (m_size > 0U )
220263 {
221- at_unchecked (--m_size).~T ();
264+ if constexpr (std::is_trivial<T>::value)
265+ {
266+ m_size--;
267+ }
268+ else
269+ {
270+ at_unchecked (--m_size).~T ();
271+ }
222272 return true ;
223273 }
224274 return false ;
@@ -359,13 +409,26 @@ inline bool vector<T, Capacity>::erase(iterator position) noexcept
359409 // AXIVION Next Line AutosarC++19_03-M5.0.9 : False positive. Pointer arithmetic occurs here.
360410 uint64_t index{static_cast <uint64_t >(position - begin ())};
361411 uint64_t n{index};
362- while ((n + 1U ) < size ())
412+ if constexpr (std::is_trivially_copyable<T>::value)
413+ {
414+ if constexpr (!(std::is_trivially_destructible<T>::value))
415+ {
416+ at_unchecked (n).~T ();
417+ }
418+ uint64_t dataLen{size () - n - 1U };
419+ std::memmove (data () + n, data () + n + 1U , dataLen * sizeof (T));
420+ }
421+ else
363422 {
364- // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
365- at (n) = std::move (at (n + 1U ));
366- ++n;
423+ while ((n + 1U ) < size ())
424+ {
425+ // AXIVION Next Line AutosarC++19_03-A5.0.1 : Expands to basic variable assignment. Evaluation order is inconsequential.
426+ at_unchecked (n) = std::move (at (n + 1U ));
427+ ++n;
428+ }
429+ at_unchecked (n).~T ();
367430 }
368- at (n). ~T ();
431+
369432 m_size--;
370433 return true ;
371434 }
@@ -391,9 +454,16 @@ inline const T& vector<T, Capacity>::at_unchecked(const uint64_t index) const no
391454template <typename T, uint64_t Capacity>
392455inline void vector<T, Capacity>::clearFrom(const uint64_t startPosition) noexcept
393456{
394- while (m_size > startPosition )
457+ if constexpr (std::is_trivially_destructible<T>::value )
395458 {
396- at_unchecked (--m_size).~T ();
459+ m_size = startPosition;
460+ }
461+ else
462+ {
463+ while (m_size > startPosition)
464+ {
465+ at_unchecked (--m_size).~T ();
466+ }
397467 }
398468}
399469
0 commit comments