10#ifndef XTENSOR_STORAGE_HPP
11#define XTENSOR_STORAGE_HPP
16#include <initializer_list>
21#include "../core/xtensor_config.hpp"
22#include "../utils/xexception.hpp"
23#include "../utils/xtensor_simd.hpp"
24#include "../utils/xutils.hpp"
33 template <
class T,
class A = std::allocator<T>>
38 using allocator_type = A;
40 using value_type =
typename std::allocator_traits<A>::value_type;
41 using reference = value_type&;
42 using const_reference =
const value_type&;
43 using pointer =
typename std::allocator_traits<A>::pointer;
44 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
46 using size_type =
typename std::allocator_traits<A>::size_type;
47 using difference_type =
typename std::allocator_traits<A>::difference_type;
49 using iterator = pointer;
50 using const_iterator = const_pointer;
51 using reverse_iterator = std::reverse_iterator<iterator>;
52 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
55 explicit uvector(
const allocator_type& alloc)
noexcept;
56 explicit uvector(size_type count,
const allocator_type& alloc = allocator_type());
57 uvector(size_type count, const_reference value,
const allocator_type& alloc = allocator_type());
59 template <std::input_iterator InputIt>
60 uvector(InputIt first, InputIt last,
const allocator_type& alloc = allocator_type());
62 uvector(std::initializer_list<T> init,
const allocator_type& alloc = allocator_type());
66 uvector(
const uvector& rhs);
67 uvector(
const uvector& rhs,
const allocator_type& alloc);
68 uvector& operator=(
const uvector&);
70 uvector(uvector&& rhs)
noexcept;
71 uvector(uvector&& rhs,
const allocator_type& alloc)
noexcept;
72 uvector& operator=(uvector&& rhs)
noexcept;
74 allocator_type get_allocator()
const noexcept;
76 bool empty()
const noexcept;
77 size_type size()
const noexcept;
78 void resize(size_type size);
79 size_type max_size()
const noexcept;
80 void reserve(size_type new_cap);
81 size_type capacity()
const noexcept;
85 reference operator[](size_type i);
86 const_reference operator[](size_type i)
const;
88 reference at(size_type i);
89 const_reference at(size_type i)
const;
92 const_reference front()
const;
95 const_reference back()
const;
97 pointer data()
noexcept;
98 const_pointer data()
const noexcept;
100 iterator begin()
noexcept;
101 iterator end()
noexcept;
103 const_iterator begin()
const noexcept;
104 const_iterator end()
const noexcept;
106 const_iterator cbegin()
const noexcept;
107 const_iterator cend()
const noexcept;
109 reverse_iterator rbegin()
noexcept;
110 reverse_iterator rend()
noexcept;
112 const_reverse_iterator rbegin()
const noexcept;
113 const_reverse_iterator rend()
const noexcept;
115 const_reverse_iterator crbegin()
const noexcept;
116 const_reverse_iterator crend()
const noexcept;
118 void swap(uvector& rhs)
noexcept;
123 void init_data(I first, I last);
125 void resize_impl(size_type new_size);
127 allocator_type m_allocator;
135 template <
class T,
class A>
138 template <
class T,
class A>
141 template <
class T,
class A>
144 template <
class T,
class A>
147 template <
class T,
class A>
150 template <
class T,
class A>
153 template <
class T,
class A>
163 inline typename std::allocator_traits<A>::pointer
164 safe_init_allocate(A& alloc,
typename std::allocator_traits<A>::size_type size)
166 using traits = std::allocator_traits<A>;
167 using pointer =
typename traits::pointer;
168 using value_type =
typename traits::value_type;
169 pointer res = alloc.allocate(size);
170 if (!xtrivially_default_constructible<value_type>::value)
172 for (pointer p = res; p != res + size; ++p)
174 traits::construct(alloc, p, value_type());
181 inline void safe_destroy_deallocate(
183 typename std::allocator_traits<A>::pointer ptr,
184 typename std::allocator_traits<A>::size_type size
187 using traits = std::allocator_traits<A>;
188 using pointer =
typename traits::pointer;
189 using value_type =
typename traits::value_type;
192 if (!xtrivially_default_constructible<value_type>::value)
194 for (pointer p = ptr; p != ptr + size; ++p)
196 traits::destroy(alloc, p);
199 traits::deallocate(alloc, ptr, size);
204 template <
class T,
class A>
206 inline void uvector<T, A>::init_data(I first, I last)
208 size_type size =
static_cast<size_type
>(std::distance(first, last));
209 if (size != size_type(0))
211 p_begin = m_allocator.allocate(size);
212 std::uninitialized_copy(first, last, p_begin);
213 p_end = p_begin + size;
217 template <
class T,
class A>
218 inline void uvector<T, A>::resize_impl(size_type new_size)
220 size_type old_size = size();
221 pointer old_begin = p_begin;
222 if (new_size != old_size)
224 p_begin = detail::safe_init_allocate(m_allocator, new_size);
225 p_end = p_begin + new_size;
226 detail::safe_destroy_deallocate(m_allocator, old_begin, old_size);
230 template <
class T,
class A>
231 inline uvector<T, A>::uvector() noexcept
236 template <
class T,
class A>
237 inline uvector<T, A>::uvector(
const allocator_type& alloc) noexcept
244 template <
class T,
class A>
245 inline uvector<T, A>::uvector(size_type count,
const allocator_type& alloc)
252 p_begin = detail::safe_init_allocate(m_allocator, count);
253 p_end = p_begin + count;
257 template <
class T,
class A>
258 inline uvector<T, A>::uvector(size_type count, const_reference value,
const allocator_type& alloc)
265 p_begin = m_allocator.allocate(count);
266 p_end = p_begin + count;
267 std::uninitialized_fill(p_begin, p_end, value);
271 template <
class T,
class A>
272 template <std::input_iterator InputIt>
273 inline uvector<T, A>::uvector(InputIt first, InputIt last,
const allocator_type& alloc)
278 init_data(first, last);
281 template <
class T,
class A>
282 inline uvector<T, A>::uvector(std::initializer_list<T> init,
const allocator_type& alloc)
287 init_data(init.begin(), init.end());
290 template <
class T,
class A>
291 inline uvector<T, A>::~uvector()
293 detail::safe_destroy_deallocate(m_allocator, p_begin, size());
298 template <
class T,
class A>
299 inline uvector<T, A>::uvector(
const uvector& rhs)
301 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
306 init_data(rhs.p_begin, rhs.p_end);
309 template <
class T,
class A>
310 inline uvector<T, A>::uvector(
const uvector& rhs,
const allocator_type& alloc)
315 init_data(rhs.p_begin, rhs.p_end);
318 template <
class T,
class A>
324 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
327 resize_impl(rhs.size());
328 if (xtrivially_default_constructible<value_type>::value)
330 std::uninitialized_copy(rhs.p_begin, rhs.p_end, p_begin);
334 std::copy(rhs.p_begin, rhs.p_end, p_begin);
340 template <
class T,
class A>
341 inline uvector<T, A>::uvector(
uvector&& rhs) noexcept
342 : m_allocator(std::move(rhs.m_allocator))
343 , p_begin(rhs.p_begin)
346 rhs.p_begin =
nullptr;
350 template <
class T,
class A>
351 inline uvector<T, A>::uvector(
uvector&& rhs,
const allocator_type& alloc) noexcept
353 , p_begin(rhs.p_begin)
356 rhs.p_begin =
nullptr;
360 template <
class T,
class A>
365 swap(p_begin, tmp.p_begin);
366 swap(p_end, tmp.p_end);
370 template <
class T,
class A>
371 inline auto uvector<T, A>::get_allocator() const noexcept -> allocator_type
373 return allocator_type(m_allocator);
376 template <
class T,
class A>
377 inline bool uvector<T, A>::empty() const noexcept
379 return size() == size_type(0);
382 template <
class T,
class A>
383 inline auto uvector<T, A>::size() const noexcept -> size_type
385 return static_cast<size_type
>(p_end - p_begin);
388 template <
class T,
class A>
389 inline void uvector<T, A>::resize(size_type size)
394 template <
class T,
class A>
395 inline auto uvector<T, A>::max_size() const noexcept -> size_type
397 return m_allocator.max_size();
400 template <
class T,
class A>
401 inline void uvector<T, A>::reserve(size_type )
405 template <
class T,
class A>
406 inline auto uvector<T, A>::capacity() const noexcept -> size_type
411 template <
class T,
class A>
412 inline void uvector<T, A>::shrink_to_fit()
416 template <
class T,
class A>
417 inline void uvector<T, A>::clear()
419 resize(size_type(0));
422 template <
class T,
class A>
423 inline auto uvector<T, A>::operator[](size_type i) -> reference
428 template <
class T,
class A>
429 inline auto uvector<T, A>::operator[](size_type i)
const -> const_reference
434 template <
class T,
class A>
435 inline auto uvector<T, A>::at(size_type i) -> reference
439 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
441 return this->operator[](i);
444 template <
class T,
class A>
445 inline auto uvector<T, A>::at(size_type i)
const -> const_reference
449 XTENSOR_THROW(std::out_of_range,
"Out of range in uvector access");
451 return this->operator[](i);
454 template <
class T,
class A>
455 inline auto uvector<T, A>::front() -> reference
460 template <
class T,
class A>
461 inline auto uvector<T, A>::front() const -> const_reference
466 template <
class T,
class A>
467 inline auto uvector<T, A>::back() -> reference
472 template <
class T,
class A>
473 inline auto uvector<T, A>::back() const -> const_reference
478 template <
class T,
class A>
479 inline auto uvector<T, A>::data() noexcept -> pointer
484 template <
class T,
class A>
485 inline auto uvector<T, A>::data() const noexcept -> const_pointer
490 template <
class T,
class A>
491 inline auto uvector<T, A>::begin() noexcept -> iterator
496 template <
class T,
class A>
497 inline auto uvector<T, A>::end() noexcept -> iterator
502 template <
class T,
class A>
503 inline auto uvector<T, A>::begin() const noexcept -> const_iterator
508 template <
class T,
class A>
509 inline auto uvector<T, A>::end() const noexcept -> const_iterator
514 template <
class T,
class A>
515 inline auto uvector<T, A>::cbegin() const noexcept -> const_iterator
520 template <
class T,
class A>
521 inline auto uvector<T, A>::cend() const noexcept -> const_iterator
526 template <
class T,
class A>
527 inline auto uvector<T, A>::rbegin() noexcept -> reverse_iterator
529 return reverse_iterator(end());
532 template <
class T,
class A>
533 inline auto uvector<T, A>::rend() noexcept -> reverse_iterator
535 return reverse_iterator(begin());
538 template <
class T,
class A>
539 inline auto uvector<T, A>::rbegin() const noexcept -> const_reverse_iterator
541 return const_reverse_iterator(end());
544 template <
class T,
class A>
545 inline auto uvector<T, A>::rend() const noexcept -> const_reverse_iterator
547 return const_reverse_iterator(begin());
550 template <
class T,
class A>
551 inline auto uvector<T, A>::crbegin() const noexcept -> const_reverse_iterator
556 template <
class T,
class A>
557 inline auto uvector<T, A>::crend() const noexcept -> const_reverse_iterator
562 template <
class T,
class A>
566 swap(m_allocator, rhs.m_allocator);
567 swap(p_begin, rhs.p_begin);
568 swap(p_end, rhs.p_end);
571 template <
class T,
class A>
574 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
577 template <
class T,
class A>
580 return !(lhs == rhs);
583 template <
class T,
class A>
586 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
589 template <
class T,
class A>
595 template <
class T,
class A>
601 template <
class T,
class A>
607 template <
class T,
class A>
620 struct allocator_alignment
622 static constexpr std::size_t value = 0;
625 template <
class T, std::
size_t A>
626 struct allocator_alignment<xt_simd::aligned_allocator<T, A>>
628 static constexpr std::size_t value = A;
632 template <
class T, std::
size_t N = 4,
class A = std::allocator<T>,
bool Init = true>
637 using self_type = svector<T, N, A, Init>;
638 using allocator_type = A;
639 using size_type =
typename std::allocator_traits<A>::size_type;
640 using value_type =
typename std::allocator_traits<A>::value_type;
641 using pointer =
typename std::allocator_traits<A>::pointer;
642 using const_pointer =
typename std::allocator_traits<A>::const_pointer;
643 using reference = value_type&;
644 using const_reference =
const value_type&;
645 using difference_type =
typename std::allocator_traits<A>::difference_type;
647 using iterator = pointer;
648 using const_iterator = const_pointer;
649 using reverse_iterator = std::reverse_iterator<iterator>;
650 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
652#if defined(_MSC_VER) && _MSC_VER < 1910
653 static constexpr std::size_t alignment = detail::allocator_alignment<A>::value;
655 static constexpr std::size_t alignment = detail::allocator_alignment<A>::value != 0
656 ? detail::allocator_alignment<A>::value
663 explicit svector(
const allocator_type& alloc)
noexcept;
664 explicit svector(size_type n,
const allocator_type& alloc = allocator_type());
665 svector(size_type n,
const value_type& v,
const allocator_type& alloc = allocator_type());
666 svector(std::initializer_list<T> il,
const allocator_type& alloc = allocator_type());
668 svector(
const std::vector<T>& vec);
670 template <std::input_iterator IT>
671 svector(IT begin, IT end,
const allocator_type& alloc = allocator_type());
673 template <std::
size_t N2,
bool I2>
674 explicit svector(
const svector<T, N2, A, I2>& rhs)
677 svector& operator=(
const svector& rhs);
678 svector& operator=(svector&& rhs)
noexcept(std::is_nothrow_move_assignable<value_type>::value);
679 svector& operator=(
const std::vector<T>& rhs);
680 svector& operator=(std::initializer_list<T> il);
682 template <std::
size_t N2,
bool I2>
683 svector& operator=(
const svector<T, N2, A, I2>& rhs)
686 svector(
const svector& other);
687 svector(svector&& other)
noexcept(std::is_nothrow_move_constructible<value_type>::value);
689 void assign(size_type n,
const value_type& v);
692 void assign(std::initializer_list<V> il);
695 void assign(IT other_begin, IT other_end);
697 reference operator[](size_type idx);
698 const_reference operator[](size_type idx)
const;
700 reference at(size_type idx);
701 const_reference at(size_type idx)
const;
704 const_pointer data()
const;
706 void push_back(
const T& elt);
707 void push_back(T&& elt);
711 const_iterator begin()
const;
712 const_iterator cbegin()
const;
714 const_iterator end()
const;
715 const_iterator cend()
const;
717 reverse_iterator rbegin();
718 const_reverse_iterator rbegin()
const;
719 const_reverse_iterator crbegin()
const;
720 reverse_iterator rend();
721 const_reverse_iterator rend()
const;
722 const_reverse_iterator crend()
const;
725 size_type size()
const;
726 void resize(size_type n);
727 size_type max_size()
const noexcept;
728 size_type capacity()
const;
729 void reserve(size_type n);
730 void shrink_to_fit();
734 const_reference front()
const;
736 const_reference back()
const;
740 iterator erase(const_iterator cit);
741 iterator erase(const_iterator cfirst, const_iterator clast);
743 iterator insert(const_iterator it,
const T& elt);
746 iterator insert(const_iterator pos, It first, It last);
748 iterator insert(const_iterator pos, std::initializer_list<T> l);
750 template <std::
size_t ON,
class OA,
bool InitA>
751 void swap(svector<T, ON, OA, InitA>& rhs);
753 allocator_type get_allocator()
const noexcept;
759 T* m_begin = std::begin(m_data);
760 T* m_end = std::begin(m_data);
761 T* m_capacity = std::end(m_data);
764 alignas(alignment) T m_data[N > 0 ? N : 1];
766 void grow(size_type min_capacity = 0);
767 void destroy_range(T* begin, T* end);
770 template <
class T, std::
size_t N,
class A,
bool Init>
771 inline svector<T, N, A, Init>::~svector()
775 detail::safe_destroy_deallocate(m_allocator, m_begin,
static_cast<std::size_t
>(m_capacity - m_begin));
779 template <
class T, std::
size_t N,
class A,
bool Init>
780 inline svector<T, N, A, Init>::svector() noexcept
785 template <
class T, std::
size_t N,
class A,
bool Init>
786 inline svector<T, N, A, Init>::svector(
const allocator_type& alloc) noexcept
791 template <
class T, std::
size_t N,
class A,
bool Init>
792 inline svector<T, N, A, Init>::svector(size_type n,
const allocator_type& alloc)
805 template <
class T, std::
size_t N,
class A,
bool Init>
806 template <std::input_iterator IT>
807 inline svector<T, N, A, Init>::svector(IT begin, IT end,
const allocator_type& alloc)
813 template <
class T, std::
size_t N,
class A,
bool Init>
814 template <std::
size_t N2,
bool I2>
817 : m_allocator(rhs.get_allocator())
819 assign(rhs.begin(), rhs.end());
822 template <
class T, std::
size_t N,
class A,
bool Init>
823 inline svector<T, N, A, Init>::svector(
const std::vector<T>& vec)
825 assign(vec.begin(), vec.end());
828 template <
class T, std::
size_t N,
class A,
bool Init>
829 inline svector<T, N, A, Init>::svector(size_type n,
const value_type& v,
const allocator_type& alloc)
835 template <
class T, std::
size_t N,
class A,
bool Init>
836 inline svector<T, N, A, Init>::svector(std::initializer_list<T> il,
const allocator_type& alloc)
839 assign(il.begin(), il.end());
842 template <
class T, std::
size_t N,
class A,
bool Init>
845 assign(rhs.begin(), rhs.end());
849 template <
class T, std::
size_t N,
class A,
bool Init>
851 )
noexcept(std::is_nothrow_move_assignable<value_type>::value)
853 assign(rhs.begin(), rhs.end());
857 template <
class T, std::
size_t N,
class A,
bool Init>
860 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
863 assign(rhs.begin(), rhs.end());
867 template <
class T, std::
size_t N,
class A,
bool Init>
870 return operator=(self_type(il));
873 template <
class T, std::
size_t N,
class A,
bool Init>
874 template <std::
size_t N2,
bool I2>
878 m_allocator = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
881 assign(rhs.begin(), rhs.end());
885 template <
class T, std::
size_t N,
class A,
bool Init>
886 inline svector<T, N, A, Init>::svector(
const svector& rhs)
888 std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator())
891 assign(rhs.begin(), rhs.end());
894 template <
class T, std::
size_t N,
class A,
bool Init>
895 inline svector<T, N, A, Init>::svector(
svector&& rhs
896 )
noexcept(std::is_nothrow_move_constructible<value_type>::value)
901 template <
class T, std::
size_t N,
class A,
bool Init>
902 inline void svector<T, N, A, Init>::assign(size_type n,
const value_type& v)
904 if (n > N && n > capacity())
909 std::fill(begin(), end(), v);
912 template <
class T, std::
size_t N,
class A,
bool Init>
914 inline void svector<T, N, A, Init>::assign(std::initializer_list<V> il)
916 assign(il.begin(), il.end());
919 template <
class T, std::
size_t N,
class A,
bool Init>
921 inline void svector<T, N, A, Init>::assign(IT other_begin, IT other_end)
923 std::size_t size =
static_cast<std::size_t
>(other_end - other_begin);
924 if (size > N && size > capacity())
928 std::uninitialized_copy(other_begin, other_end, m_begin);
929 m_end = m_begin + size;
932 template <
class T, std::
size_t N,
class A,
bool Init>
933 inline auto svector<T, N, A, Init>::operator[](size_type idx) -> reference
938 template <
class T, std::
size_t N,
class A,
bool Init>
939 inline auto svector<T, N, A, Init>::operator[](size_type idx)
const -> const_reference
944 template <
class T, std::
size_t N,
class A,
bool Init>
945 inline auto svector<T, N, A, Init>::at(size_type idx) -> reference
949 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
951 return this->operator[](idx);
954 template <
class T, std::
size_t N,
class A,
bool Init>
955 inline auto svector<T, N, A, Init>::at(size_type idx)
const -> const_reference
959 XTENSOR_THROW(std::out_of_range,
"Out of range in svector access");
961 return this->operator[](idx);
964 template <
class T, std::
size_t N,
class A,
bool Init>
965 inline auto svector<T, N, A, Init>::data() -> pointer
970 template <
class T, std::
size_t N,
class A,
bool Init>
971 inline auto svector<T, N, A, Init>::data() const -> const_pointer
976 template <
class T, std::
size_t N,
class A,
bool Init>
977 void svector<T, N, A, Init>::resize(size_type n)
979 if (n > N && n > capacity())
983 size_type old_size = size();
985 if (Init && old_size < size())
987 std::fill(begin() + old_size, end(), T());
991 template <
class T, std::
size_t N,
class A,
bool Init>
992 inline auto svector<T, N, A, Init>::max_size() const noexcept -> size_type
994 return m_allocator.max_size();
997 template <
class T, std::
size_t N,
class A,
bool Init>
998 inline auto svector<T, N, A, Init>::capacity() const -> size_type
1000 return static_cast<std::size_t
>(m_capacity - m_begin);
1003 template <
class T, std::
size_t N,
class A,
bool Init>
1004 inline void svector<T, N, A, Init>::reserve(size_type n)
1006 if (n > N && n > capacity())
1012 template <
class T, std::
size_t N,
class A,
bool Init>
1013 inline void svector<T, N, A, Init>::shrink_to_fit()
1018 template <
class T, std::
size_t N,
class A,
bool Init>
1019 inline void svector<T, N, A, Init>::clear()
1021 resize(size_type(0));
1024 template <
class T, std::
size_t N,
class A,
bool Init>
1025 void svector<T, N, A, Init>::push_back(
const T& elt)
1027 if (m_end >= m_capacity)
1034 template <
class T, std::
size_t N,
class A,
bool Init>
1035 void svector<T, N, A, Init>::push_back(T&& elt)
1037 if (m_end >= m_capacity)
1041 *(m_end++) = std::move(elt);
1044 template <
class T, std::
size_t N,
class A,
bool Init>
1045 void svector<T, N, A, Init>::pop_back()
1050 template <
class T, std::
size_t N,
class A,
bool Init>
1051 inline auto svector<T, N, A, Init>::begin() -> iterator
1056 template <
class T, std::
size_t N,
class A,
bool Init>
1057 inline auto svector<T, N, A, Init>::begin() const -> const_iterator
1062 template <
class T, std::
size_t N,
class A,
bool Init>
1063 inline auto svector<T, N, A, Init>::cbegin() const -> const_iterator
1068 template <
class T, std::
size_t N,
class A,
bool Init>
1069 inline auto svector<T, N, A, Init>::end() -> iterator
1074 template <
class T, std::
size_t N,
class A,
bool Init>
1075 inline auto svector<T, N, A, Init>::end() const -> const_iterator
1080 template <
class T, std::
size_t N,
class A,
bool Init>
1081 inline auto svector<T, N, A, Init>::cend() const -> const_iterator
1086 template <
class T, std::
size_t N,
class A,
bool Init>
1087 inline auto svector<T, N, A, Init>::rbegin() -> reverse_iterator
1089 return reverse_iterator(m_end);
1092 template <
class T, std::
size_t N,
class A,
bool Init>
1093 inline auto svector<T, N, A, Init>::rbegin() const -> const_reverse_iterator
1095 return const_reverse_iterator(m_end);
1098 template <
class T, std::
size_t N,
class A,
bool Init>
1099 inline auto svector<T, N, A, Init>::crbegin() const -> const_reverse_iterator
1101 return const_reverse_iterator(m_end);
1104 template <
class T, std::
size_t N,
class A,
bool Init>
1105 inline auto svector<T, N, A, Init>::rend() -> reverse_iterator
1107 return reverse_iterator(m_begin);
1110 template <
class T, std::
size_t N,
class A,
bool Init>
1111 inline auto svector<T, N, A, Init>::rend() const -> const_reverse_iterator
1113 return const_reverse_iterator(m_begin);
1116 template <
class T, std::
size_t N,
class A,
bool Init>
1117 inline auto svector<T, N, A, Init>::crend() const -> const_reverse_iterator
1119 return const_reverse_iterator(m_begin);
1122 template <
class T, std::
size_t N,
class A,
bool Init>
1123 inline auto svector<T, N, A, Init>::size() const -> size_type
1125 return static_cast<size_type
>(m_end - m_begin);
1128 template <
class T, std::
size_t N,
class A,
bool Init>
1129 inline auto svector<T, N, A, Init>::empty() const ->
bool
1131 return m_begin == m_end;
1134 template <
class T, std::
size_t N,
class A,
bool Init>
1135 inline auto svector<T, N, A, Init>::front() -> reference
1137 XTENSOR_ASSERT(!
empty());
1141 template <
class T, std::
size_t N,
class A,
bool Init>
1142 inline auto svector<T, N, A, Init>::front() const -> const_reference
1144 XTENSOR_ASSERT(!
empty());
1148 template <
class T, std::
size_t N,
class A,
bool Init>
1149 inline auto svector<T, N, A, Init>::back() -> reference
1151 XTENSOR_ASSERT(!
empty());
1155 template <
class T, std::
size_t N,
class A,
bool Init>
1156 inline auto svector<T, N, A, Init>::back() const -> const_reference
1158 XTENSOR_ASSERT(!
empty());
1162 template <
class T, std::
size_t N,
class A,
bool Init>
1163 inline auto svector<T, N, A, Init>::on_stack() ->
bool
1165 return m_begin == &m_data[0];
1168 template <
class T, std::
size_t N,
class A,
bool Init>
1169 inline auto svector<T, N, A, Init>::get_allocator() const noexcept -> allocator_type
1174 template <
class T, std::
size_t N,
class A,
bool Init>
1175 inline auto svector<T, N, A, Init>::erase(const_iterator cit) -> iterator
1177 auto it =
const_cast<pointer
>(cit);
1178 iterator ret_val = it;
1179 std::move(it + 1, m_end, it);
1184 template <
class T, std::
size_t N,
class A,
bool Init>
1185 inline auto svector<T, N, A, Init>::erase(const_iterator cfirst, const_iterator clast) -> iterator
1187 auto first =
const_cast<pointer
>(cfirst);
1188 auto last =
const_cast<pointer
>(clast);
1195 iterator new_end = std::move(last, m_end, first);
1200 template <
class T, std::
size_t N,
class A,
bool Init>
1201 inline auto svector<T, N, A, Init>::insert(const_iterator cit,
const T& elt) -> iterator
1203 auto it =
const_cast<pointer
>(cit);
1210 if (m_end >= m_capacity)
1212 std::ptrdiff_t elt_no = it - m_begin;
1214 it = m_begin + elt_no;
1218 std::move_backward(it, m_end - 1, m_end);
1222 const T* elt_ptr = &elt;
1223 bool cond = it <= elt_ptr && elt_ptr < m_end;
1226 const T* src_ptr = cond ? it + (elt_ptr - it) + std::ptrdiff_t(1) : elt_ptr;
1231 template <
class T, std::
size_t N,
class A,
bool Init>
1233 inline auto svector<T, N, A, Init>::insert(const_iterator pos, It first, It last) -> iterator
1235 auto it =
const_cast<pointer
>(pos);
1236 difference_type n = std::distance(first, last);
1239 if (n > m_capacity - m_end)
1241 std::ptrdiff_t elt_no = it - m_begin;
1242 grow(
static_cast<size_t>((m_capacity - m_begin) + n));
1243 it = m_begin + elt_no;
1246 std::move_backward(it, m_end, m_end + n);
1248 std::copy(first, last, it);
1253 template <
class T, std::
size_t N,
class A,
bool Init>
1254 inline auto svector<T, N, A, Init>::insert(const_iterator pos, std::initializer_list<T> l) -> iterator
1256 return insert(pos, l.begin(), l.end());
1259 template <
class T, std::
size_t N,
class A,
bool Init>
1260 inline void svector<T, N, A, Init>::destroy_range(T* begin, T* end)
1262 if (!xtrivially_default_constructible<T>::value)
1264 while (begin != end)
1272 template <
class T, std::
size_t N,
class A,
bool Init>
1273 template <std::
size_t ON,
class OA,
bool InitA>
1283 if (!this->on_stack() && !rhs.on_stack())
1285 swap(this->m_begin, rhs.m_begin);
1286 swap(this->m_end, rhs.m_end);
1287 swap(this->m_capacity, rhs.m_capacity);
1291 size_type rhs_old_size = rhs.size();
1292 size_type old_size = this->size();
1294 if (rhs_old_size > old_size)
1296 this->resize(rhs_old_size);
1298 else if (old_size > rhs_old_size)
1300 rhs.resize(old_size);
1304 size_type min_size = (std::min)(old_size, rhs_old_size);
1305 for (size_type i = 0; i < min_size; ++i)
1307 swap((*
this)[i], rhs[i]);
1311 if (old_size > rhs_old_size)
1313 std::copy(this->begin() + min_size, this->end(), rhs.begin() + min_size);
1314 this->destroy_range(this->begin() + min_size, this->end());
1315 this->m_end = this->begin() + min_size;
1317 else if (rhs_old_size > old_size)
1319 std::copy(rhs.begin() + min_size, rhs.end(), this->begin() + min_size);
1320 this->destroy_range(rhs.begin() + min_size, rhs.end());
1321 rhs.m_end = rhs.begin() + min_size;
1325 template <
class T, std::
size_t N,
class A,
bool Init>
1326 inline void svector<T, N, A, Init>::grow(size_type min_capacity)
1328 size_type current_size = size();
1329 size_type new_capacity = 2 * current_size + 1;
1330 if (new_capacity < min_capacity)
1332 new_capacity = min_capacity;
1337 if (m_begin == &m_data[0])
1339 new_alloc = m_allocator.allocate(new_capacity);
1340 std::uninitialized_copy(m_begin, m_end, new_alloc);
1345 new_alloc = m_allocator.allocate(new_capacity);
1346 std::uninitialized_copy(m_begin, m_end, new_alloc);
1347 m_allocator.deallocate(m_begin, std::size_t(m_capacity - m_begin));
1349 XTENSOR_ASSERT(new_alloc);
1351 m_end = new_alloc + current_size;
1352 m_begin = new_alloc;
1353 m_capacity = new_alloc + new_capacity;
1356 template <
class T, std::
size_t N,
class A,
bool Init>
1359 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1362 template <
class T, std::
size_t N,
class A,
bool Init>
1365 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1368 template <
class T, std::
size_t N,
class A,
bool Init>
1371 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1374 template <
class T, std::
size_t N,
class A,
bool Init>
1377 return !(lhs == rhs);
1380 template <
class T, std::
size_t N,
class A,
bool Init>
1383 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1386 template <
class T, std::
size_t N,
class A,
bool Init>
1389 return !(lhs > rhs);
1392 template <
class T, std::
size_t N,
class A,
bool Init>
1398 template <
class T, std::
size_t N,
class A,
bool Init>
1401 return !(lhs < rhs);
1404 template <
class T, std::
size_t N,
class A,
bool Init>
1410 template <
class X,
class T, std::
size_t N,
class A,
bool B>
1413 using traits = std::allocator_traits<A>;
1414 using allocator =
typename traits::template rebind_alloc<X>;
1424 template <
class T, std::
size_t N, std::
size_t Align = XTENSOR_
SELECT_ALIGN(T)>
1431 using allocator_type = std::conditional_t<Align != 0, xt_simd::aligned_allocator<T, Align>, std::allocator<T>>;
1434#if defined(_MSC_VER)
1435#define XTENSOR_CONST
1437#define XTENSOR_CONST const
1440#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
1441#define GCC4_FALLBACK
1443 namespace const_array_detail
1445 template <
class T, std::
size_t N>
1448 using storage_type = T[N];
1450 static constexpr T& ref(
const storage_type& t, std::size_t n)
noexcept
1452 return const_cast<T&
>(t[n]);
1455 static constexpr T* ptr(
const storage_type& t)
noexcept
1457 return const_cast<T*
>(t);
1462 struct array_traits<T, 0>
1468 using storage_type =
empty;
1470 static constexpr T& ref(
const storage_type& , std::size_t )
noexcept
1472 return *
static_cast<T*
>(
nullptr);
1475 static constexpr T* ptr(
const storage_type& )
noexcept
1487 template <
class T, std::
size_t N>
1490 using size_type = std::size_t;
1491 using value_type = T;
1492 using pointer = value_type*;
1493 using const_pointer =
const value_type*;
1494 using reference = value_type&;
1495 using const_reference =
const value_type&;
1496 using difference_type = std::ptrdiff_t;
1497 using iterator = pointer;
1498 using const_iterator = const_pointer;
1500 using reverse_iterator = std::reverse_iterator<const_iterator>;
1501 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1503 constexpr const_reference operator[](std::size_t idx)
const
1506 return const_array_detail::array_traits<T, N>::ref(m_data, idx);
1512 constexpr const_iterator begin()
const noexcept
1517 constexpr const_iterator end()
const noexcept
1522 constexpr const_iterator cbegin()
const noexcept
1527 constexpr const_iterator cend()
const noexcept
1533 reverse_iterator rbegin()
const noexcept
1538 reverse_iterator rend()
const noexcept
1543 const_reverse_iterator crbegin()
const noexcept
1545 return const_reverse_iterator(end());
1548 const_reverse_iterator crend()
const noexcept
1550 return const_reverse_iterator(begin());
1553 constexpr const_pointer data()
const noexcept
1556 return const_array_detail::array_traits<T, N>::ptr(m_data);
1562 constexpr const_reference front()
const noexcept
1565 return const_array_detail::array_traits<T, N>::ref(m_data, 0);
1571 constexpr const_reference back()
const noexcept
1574 return N ? const_array_detail::array_traits<T, N>::ref(m_data, N - 1)
1575 : const_array_detail::array_traits<T, N>::ref(m_data, 0);
1577 return m_data[size() - 1];
1581 constexpr bool empty()
const noexcept
1583 return size() == size_type(0);
1586 constexpr size_type size()
const noexcept
1592 XTENSOR_CONST
typename const_array_detail::array_traits<T, N>::storage_type m_data;
1594 XTENSOR_CONST T m_data[N > 0 ? N : 1];
1600 template <
class T, std::
size_t N>
1603 return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
1606 template <
class T, std::
size_t N>
1607 inline bool operator!=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1609 return !(lhs == rhs);
1612 template <
class T, std::
size_t N>
1613 inline bool operator<(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1615 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1618 template <
class T, std::
size_t N>
1619 inline bool operator<=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1621 return !(lhs > rhs);
1624 template <
class T, std::
size_t N>
1625 inline bool operator>(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1630 template <
class T, std::
size_t N>
1631 inline bool operator>=(
const const_array<T, N>& lhs,
const const_array<T, N>& rhs)
1633 return !(lhs < rhs);
1637#ifdef __cpp_template_template_args
1638 template <
class X,
class T, std::
size_t N>
1639 struct rebind_container<X, aligned_array<T, N>>
1641 using type = aligned_array<X, N>;
1644 template <
class X,
class T, std::
size_t N>
1645 struct rebind_container<X, const_array<T, N>>
1647 using type = const_array<X, N>;
1656 template <std::size_t... X>
1661#if defined(_MSC_VER)
1662 using cast_type = std::array<std::size_t,
sizeof...(X)>;
1663#define XTENSOR_FIXED_SHAPE_CONSTEXPR inline
1665 using cast_type =
const_array<std::size_t,
sizeof...(X)>;
1666#define XTENSOR_FIXED_SHAPE_CONSTEXPR constexpr
1668 using value_type = std::size_t;
1669 using size_type = std::size_t;
1670 using const_iterator =
typename cast_type::const_iterator;
1672 static constexpr std::size_t size()
1674 return sizeof...(X);
1677 template <std::
size_t idx>
1678 static constexpr auto get()
1680 using tmp_cast_type = std::array<std::size_t,
sizeof...(X)>;
1681 return std::get<idx>(tmp_cast_type{X...});
1684 XTENSOR_FIXED_SHAPE_CONSTEXPR
operator cast_type()
const
1686 return cast_type({X...});
1689 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto begin()
const
1691 return m_array.begin();
1694 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto end()
const
1696 return m_array.end();
1701 return m_array.rbegin();
1706 return m_array.rend();
1709 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto cbegin()
const
1711 return m_array.cbegin();
1714 XTENSOR_FIXED_SHAPE_CONSTEXPR
auto cend()
const
1716 return m_array.cend();
1719 XTENSOR_FIXED_SHAPE_CONSTEXPR std::size_t operator[](std::size_t idx)
const
1721 return m_array[idx];
1724 XTENSOR_FIXED_SHAPE_CONSTEXPR
bool empty()
const
1726 return sizeof...(X) == 0;
1731 XTENSOR_CONSTEXPR_ENHANCED_STATIC cast_type m_array = cast_type({X...});
1734#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
1735 template <std::size_t... X>
1739#undef XTENSOR_FIXED_SHAPE_CONSTEXPR
1741 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End = -1>
1746 using value_type =
typename E::value_type;
1747 using reference =
typename E::reference;
1748 using const_reference =
typename E::const_reference;
1749 using pointer =
typename E::pointer;
1750 using const_pointer =
typename E::const_pointer;
1752 using size_type =
typename E::size_type;
1753 using difference_type =
typename E::difference_type;
1755 using iterator =
typename E::iterator;
1756 using const_iterator =
typename E::const_iterator;
1757 using reverse_iterator =
typename E::reverse_iterator;
1758 using const_reverse_iterator =
typename E::const_reverse_iterator;
1760 explicit sequence_view(
const E& container);
1762 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1763 explicit sequence_view(
const sequence_view<E, OS, OE>& other);
1765 template <class T, class R = decltype(std::declval<T>().begin())>
1769 size_type size()
const;
1770 const_reference operator[](std::size_t idx)
const;
1772 const_iterator end()
const;
1773 const_iterator begin()
const;
1774 const_iterator cend()
const;
1775 const_iterator cbegin()
const;
1777 const_reverse_iterator rend()
const;
1778 const_reverse_iterator rbegin()
const;
1779 const_reverse_iterator crend()
const;
1780 const_reverse_iterator crbegin()
const;
1782 const_reference front()
const;
1783 const_reference back()
const;
1785 const E& storage()
const;
1789 const E& m_sequence;
1792 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1793 sequence_view<E, Start, End>::sequence_view(
const E& container)
1794 : m_sequence(container)
1798 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1799 template <std::ptrdiff_t OS, std::ptrdiff_t OE>
1800 sequence_view<E, Start, End>::sequence_view(
const sequence_view<E, OS, OE>& other)
1801 : m_sequence(other.storage())
1805 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1806 template <
class T,
class R>
1809 T ret = xtl::make_sequence<T>(this->size());
1810 std::copy(this->cbegin(), this->cend(), ret.begin());
1814 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1815 bool sequence_view<E, Start, End>::empty()
const
1817 return size() == size_type(0);
1820 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1821 auto sequence_view<E, Start, End>::size() const -> size_type
1825 return m_sequence.size() -
static_cast<size_type
>(Start);
1829 return static_cast<size_type
>(End - Start);
1833 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1834 auto sequence_view<E, Start, End>::operator[](std::size_t idx)
const -> const_reference
1836 return m_sequence[idx +
static_cast<std::size_t
>(Start)];
1839 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1840 auto sequence_view<E, Start, End>::end() const -> const_iterator
1844 return m_sequence.begin() + End;
1848 return m_sequence.end();
1852 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1853 auto sequence_view<E, Start, End>::begin() const -> const_iterator
1855 return m_sequence.begin() + Start;
1858 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1859 auto sequence_view<E, Start, End>::cend() const -> const_iterator
1864 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1865 auto sequence_view<E, Start, End>::cbegin() const -> const_iterator
1870 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1871 auto sequence_view<E, Start, End>::rend() const -> const_reverse_iterator
1873 return const_reverse_iterator(begin());
1876 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1877 auto sequence_view<E, Start, End>::rbegin() const -> const_reverse_iterator
1879 return const_reverse_iterator(end());
1882 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1883 auto sequence_view<E, Start, End>::crend() const -> const_reverse_iterator
1888 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1889 auto sequence_view<E, Start, End>::crbegin() const -> const_reverse_iterator
1894 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1895 auto sequence_view<E, Start, End>::front() const -> const_reference
1897 return *(m_sequence.begin() + Start);
1900 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1901 auto sequence_view<E, Start, End>::back() const -> const_reference
1905 return m_sequence.back();
1909 return m_sequence[
static_cast<std::size_t
>(End - 1)];
1913 template <
class E, std::ptrdiff_t Start, std::ptrdiff_t End>
1914 const E& sequence_view<E, Start, End>::storage()
const
1919 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1922 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
1925 template <
class T, std::ptrdiff_t TB, std::ptrdiff_t TE>
1928 return !(lhs == rhs);
1942#if defined(__clang__)
1943 # pragma clang diagnostic push
1944 # pragma clang diagnostic ignored "-Wmismatched-tags"
1950 template <
class T, std::
size_t N>
1951 class tuple_size<
xt::const_array<T, N>> :
public integral_constant<std::size_t, N>
1955 template <std::size_t... N>
1956 class tuple_size<
xt::fixed_shape<N...>> :
public integral_constant<std::size_t, sizeof...(N)>
1960 template <
class T, std::ptrdiff_t Start, std::ptrdiff_t End>
1961 class tuple_size<
xt::sequence_view<T, Start, End>>
1962 :
public integral_constant<std::size_t, std::size_t(End - Start)>
1967 template <
class T, std::ptrdiff_t Start>
1968 class tuple_size<
xt::sequence_view<T, Start, -1>>;
1973#if defined(__clang__)
1974 # pragma clang diagnostic pop
This array class is modeled after std::array but adds optional alignment through a template parameter...
Fixed shape implementation for compile time defined arrays.
standard mathematical functions for xexpressions
xarray< T, L > empty(const S &shape)
Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of with value_type T...
A std::array like class with all member function (except reverse iterators) as constexpr.