29 #ifndef PIRANHA_STATIC_VECTOR_HPP 30 #define PIRANHA_STATIC_VECTOR_HPP 40 #include <type_traits> 42 #include <piranha/config.hpp> 43 #include <piranha/detail/small_vector_fwd.hpp> 44 #include <piranha/detail/vector_hasher.hpp> 46 #include <piranha/s11n.hpp> 47 #include <piranha/safe_cast.hpp> 58 using static_vector_size_types = std::tuple<unsigned char, unsigned short, unsigned, unsigned long, unsigned long long>;
60 template <std::
size_t Size, std::
size_t Index = 0u>
61 struct static_vector_size_type {
62 using candidate_type =
typename std::tuple_element<Index, static_vector_size_types>::type;
63 using type =
typename std::
64 conditional<(std::numeric_limits<candidate_type>::max() >= Size), candidate_type,
65 typename static_vector_size_type<Size, static_cast<std::size_t>(Index + 1u)>::type>::type;
68 template <std::
size_t Size>
69 struct static_vector_size_type<Size, static_cast<
std::size_t>(std::tuple_size<static_vector_size_types>::value - 1u)> {
71 typename std::tuple_element<static_cast<std::size_t>(std::tuple_size<static_vector_size_types>::value - 1u),
72 static_vector_size_types>::type;
73 static_assert(std::numeric_limits<type>::max() >= Size,
"Cannot determine size type for static vector.");
98 template <
typename T, std::
size_t MaxSize>
101 #if !defined(PIRANHA_DOXYGEN_INVOKED) 102 static_assert(MaxSize > 0u,
"Maximum size must be strictly positive.");
104 template <
typename,
typename>
105 friend union detail::small_vector_union;
112 using size_type =
typename detail::static_vector_size_type<MaxSize>::type;
115 #if !defined(PIRANHA_DOXYGEN_INVOKED) 118 static_assert(std::numeric_limits<size_type>::max() <= std::numeric_limits<std::size_t>::max() /
sizeof(T),
119 "The size type for static_vector might overflow.");
121 static_assert(MaxSize < std::numeric_limits<std::size_t>::max() /
sizeof(T),
122 "Overflow in the computation of storage size.");
146 using storage_type =
typename std::aligned_storage<sizeof(T) * MaxSize, alignof(T)>::type;
149 friend class boost::serialization::access;
150 template <
class Archive>
151 void save(Archive &ar,
unsigned)
const 153 boost_save_vector(ar, *
this);
155 template <
class Archive>
156 void load(Archive &ar,
unsigned)
158 boost_load_vector(ar, *
this);
160 BOOST_SERIALIZATION_SPLIT_MEMBER()
164 static
void default_init(T *
begin, T *
end)
167 ::new (static_cast<void *>(
begin)) T;
202 if (std::is_pod<T>::value) {
207 default_init(ptr(), ptr() +
size);
208 std::memcpy(vs(), other.vs(),
size *
sizeof(T));
228 const auto size = other.size();
229 if (std::is_pod<T>::value) {
230 default_init(ptr(), ptr() +
size);
231 std::memcpy(vs(), other.vs(),
size *
sizeof(T));
240 other.destroy_items();
272 piranha_assert(m_tag == 1u);
285 if (likely(
this != &other)) {
286 if (std::is_pod<T>::value) {
287 if (other.m_size > m_size) {
290 default_init(ptr() + m_size, ptr() + other.m_size);
292 std::memcpy(vs(), other.vs(), other.m_size *
sizeof(T));
293 m_size = other.m_size;
296 *
this = std::move(tmp);
309 if (likely(
this != &other)) {
310 if (std::is_pod<T>::value) {
311 if (other.m_size > m_size) {
312 default_init(ptr() + m_size, ptr() + other.m_size);
314 std::memcpy(vs(), other.vs(), other.m_size *
sizeof(T));
316 const size_type old_size = m_size, new_size = other.m_size;
317 if (old_size <= new_size) {
319 for (
size_type i = 0u; i < old_size; ++i) {
320 (*this)[i] = std::move(other[i]);
323 for (
size_type i = old_size; i < new_size; ++i) {
324 ::new (static_cast<void *>(ptr() + i))
value_type(std::move(other[i]));
328 for (
size_type i = 0u; i < new_size; ++i) {
329 (*this)[i] = std::move(other[i]);
332 for (
size_type i = new_size; i < old_size; ++i) {
337 m_size = other.m_size;
339 other.destroy_items();
378 return ptr() + m_size;
394 return ptr() + m_size;
407 return (m_size == other.m_size && std::equal(
begin(),
end(), other.
begin()));
432 if (unlikely(m_size == MaxSize)) {
435 ::new (static_cast<void *>(ptr() + m_size))
value_type(x);
448 if (unlikely(m_size == MaxSize)) {
451 ::new (static_cast<void *>(ptr() + m_size))
value_type(std::move(x));
456 template <
typename... Args>
457 using emplace_enabler = enable_if_t<std::is_constructible<
value_type, Args &&...>::value,
int>;
472 template <
typename... Args, emplace_enabler<Args...> = 0>
475 if (unlikely(m_size == MaxSize)) {
478 ::new (static_cast<void *>(ptr() + m_size))
value_type(std::forward<Args>(params)...);
511 if (unlikely(new_size > MaxSize)) {
514 const auto old_size = m_size;
515 if (new_size == old_size) {
517 }
else if (new_size > old_size) {
521 for (; i < new_size; ++i) {
525 ::new (static_cast<void *>(ptr() + i))
value_type();
526 piranha_assert(m_size != MaxSize);
530 for (
size_type j = old_size; j < i; ++j) {
532 piranha_assert(m_size);
539 for (
size_type i = new_size; i < old_size; ++i) {
541 piranha_assert(m_size);
565 piranha_assert(it !=
end());
569 auto retval =
const_cast<iterator>(it);
570 const auto it_f =
end() - 1;
572 for (; it != it_f; ++it) {
576 ::new (static_cast<void *>(const_cast<iterator>(it)))
value_type(std::move(*(it + 1)));
581 m_size =
static_cast<size_type>(m_size - 1u);
595 template <
typename U>
596 using hash_enabler = enable_if_t<is_hashable<U>::value,
int>;
616 template <
typename U = T, hash_enabler<U> = 0>
619 return detail::vector_hasher(*
this);
623 template <
typename U>
624 using ostream_enabler = enable_if_t<is_ostreamable<U>::value,
int>;
641 template <
typename U = T, ostream_enabler<U> = 0>
645 for (decltype(v.
size()) i = 0u; i < v.
size(); ++i) {
647 if (i != v.size() - 1u) {
663 if (std::is_trivially_destructible<T>::value) {
666 const auto size = m_size;
674 return static_cast<void *
>(&m_storage);
676 const void *vs()
const 678 return static_cast<const void *
>(&m_storage);
683 return static_cast<T *
>(vs());
687 return static_cast<const T *
>(vs());
693 storage_type m_storage;
696 template <
typename T, std::
size_t MaxSize>
707 template <
typename Archive,
typename T, std::
size_t S>
724 template <
typename Archive,
typename T, std::
size_t S>
729 #if defined(PIRANHA_WITH_MSGPACK) 739 template <
typename Stream,
typename T, std::
size_t S>
756 msgpack_pack_vector(p, v, f);
767 template <
typename T, std::
size_t S>
786 msgpack_convert_array(o, v, f);
const_iterator end() const
Const end iterator.
typename detail::static_vector_size_type< MaxSize >::type size_type
Size type.
iterator begin()
Begin iterator.
value_type * iterator
Iterator type.
static_vector(const static_vector &other)
Copy constructor.
Default implementation of piranha::boost_load().
void operator()(static_vector< T, S > &v, const msgpack::object &o, msgpack_format f) const
Call operator.
Implementation of piranha::boost_load() via the Boost API.
static_vector & operator=(const static_vector &other)
Copy assignment operator.
Default implementation of piranha::boost_save().
void emplace_back(Args &&... params)
Construct in-place at the end of the vector.
void resize(const size_type &new_size)
Resize.
const value_type & operator[](const size_type &n) const
Const subscript operator.
void operator()(msgpack::packer< Stream > &p, const static_vector< T, S > &v, msgpack_format f) const
Call operator.
Forward iterator type trait.
iterator erase(const_iterator it)
Erase element.
bool empty() const
Empty test.
Default functor for the implementation of piranha::msgpack_convert().
value_type const * const_iterator
Const iterator type.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
iterator end()
End iterator.
Default functor for the implementation of piranha::msgpack_pack().
msgpack_format
Serialization format for msgpack.
T value_type
Contained type.
static_vector & operator=(static_vector &&other) noexcept
Move assignment operator.
bool operator==(const static_vector &other) const
Equality operator.
void push_back(value_type &&x)
Move-add element at the end of the vector.
std::size_t hash() const
Hash value.
static_vector()
Default constructor.
Implementation of piranha::boost_save() via the Boost API.
value_type & operator[](const size_type &n)
Subscript operator.
void push_back(const value_type &x)
Copy-add element at the end of the vector.
~static_vector()
Destructor.
friend std::ostream & operator<<(std::ostream &os, const static_vector &v)
Stream operator overload for piranha::static_vector.
static const size_type max_size
Maximum size.
Type trait for well-behaved container elements.
#define PIRANHA_TT_CHECK(tt,...)
Macro for static type trait checks.
bool operator!=(const static_vector &other) const
Inequality operator.
static_vector(const size_type &n, const value_type &x)
Constructor from multiple copies.
static_vector(static_vector &&other) noexcept
Move constructor.
size_type size() const
Size.
const_iterator begin() const
Const begin iterator.