| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282 |
- /***************************************************************************
- * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
- * Copyright (c) QuantStack *
- * *
- * Distributed under the terms of the BSD 3-Clause License. *
- * *
- * The full license is in the file LICENSE, distributed with this software. *
- ****************************************************************************/
- #ifndef XTENSOR_BUFFER_ADAPTOR_HPP
- #define XTENSOR_BUFFER_ADAPTOR_HPP
- #include <algorithm>
- #include <functional>
- #include <iterator>
- #include <memory>
- #include <stdexcept>
- #include <xtl/xclosure.hpp>
- #include "xstorage.hpp"
- #include "xtensor_config.hpp"
- namespace xt
- {
- struct no_ownership
- {
- };
- using smart_ownership = no_ownership;
- struct acquire_ownership
- {
- };
- template <class CP, class O = no_ownership, class A = std::allocator<std::remove_pointer_t<std::remove_reference_t<CP>>>>
- class xbuffer_adaptor;
- /********************
- * buffer_storage_t *
- ********************/
- namespace detail
- {
- template <class CP, class A>
- class xbuffer_storage
- {
- public:
- using self_type = xbuffer_storage<CP, A>;
- using allocator_type = A;
- using destructor_type = allocator_type;
- using allocator_traits = std::allocator_traits<allocator_type>;
- using value_type = typename allocator_traits::value_type;
- using reference = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- const value_type&,
- value_type&>;
- using const_reference = const value_type&;
- using pointer = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- typename allocator_traits::const_pointer,
- typename allocator_traits::pointer>;
- using const_pointer = typename allocator_traits::const_pointer;
- using size_type = typename allocator_traits::size_type;
- using difference_type = typename allocator_traits::difference_type;
- xbuffer_storage();
- template <class P>
- xbuffer_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type());
- size_type size() const noexcept;
- void resize(size_type size);
- pointer data() noexcept;
- const_pointer data() const noexcept;
- void swap(self_type& rhs) noexcept;
- template <class P>
- void reset_data(P&& data, size_type size) noexcept;
- private:
- pointer p_data;
- size_type m_size;
- };
- template <class CP, class D>
- class xbuffer_smart_pointer
- {
- public:
- using self_type = xbuffer_storage<CP, D>;
- using destructor_type = D;
- using value_type = std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<CP>>>;
- using allocator_type = std::allocator<value_type>;
- using allocator_traits = std::allocator_traits<allocator_type>;
- using reference = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- const value_type&,
- value_type&>;
- using const_reference = const value_type&;
- using pointer = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- typename allocator_traits::const_pointer,
- typename allocator_traits::pointer>;
- using const_pointer = typename allocator_traits::const_pointer;
- using size_type = typename allocator_traits::size_type;
- using difference_type = typename allocator_traits::difference_type;
- xbuffer_smart_pointer();
- template <class P, class DT>
- xbuffer_smart_pointer(P&& data_ptr, size_type size, DT&& destruct);
- size_type size() const noexcept;
- void resize(size_type size);
- pointer data() noexcept;
- const_pointer data() const noexcept;
- void swap(self_type& rhs) noexcept;
- template <class P, class DT>
- void reset_data(P&& data, size_type size, DT&& destruct) noexcept;
- private:
- pointer p_data;
- size_type m_size;
- destructor_type m_destruct;
- };
- template <class CP, class A>
- class xbuffer_owner_storage
- {
- public:
- using self_type = xbuffer_owner_storage<CP, A>;
- using allocator_type = A;
- using destructor_type = allocator_type;
- using allocator_traits = std::allocator_traits<allocator_type>;
- using value_type = typename allocator_traits::value_type;
- using reference = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- const value_type&,
- value_type&>;
- using const_reference = const value_type&;
- using pointer = std::conditional_t<
- std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
- typename allocator_traits::const_pointer,
- typename allocator_traits::pointer>;
- using const_pointer = typename allocator_traits::const_pointer;
- using size_type = typename allocator_traits::size_type;
- using difference_type = typename allocator_traits::difference_type;
- xbuffer_owner_storage() = default;
- template <class P>
- xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type());
- ~xbuffer_owner_storage();
- xbuffer_owner_storage(const self_type&) = delete;
- self_type& operator=(const self_type&);
- xbuffer_owner_storage(self_type&&);
- self_type& operator=(self_type&&);
- size_type size() const noexcept;
- void resize(size_type size);
- pointer data() noexcept;
- const_pointer data() const noexcept;
- allocator_type get_allocator() const noexcept;
- void swap(self_type& rhs) noexcept;
- template <class P>
- void reset_data(P&& data, size_type size, const allocator_type& alloc = allocator_type()) noexcept;
- private:
- xtl::xclosure_wrapper<CP> m_data;
- size_type m_size;
- bool m_moved_from;
- allocator_type m_allocator;
- };
- // Workaround for MSVC2015: using void_t results in some
- // template instantiation caching that leads to wrong
- // type deduction later in xfunction.
- template <class T>
- struct msvc2015_void
- {
- using type = void;
- };
- template <class T>
- using msvc2015_void_t = typename msvc2015_void<T>::type;
- template <class E, class = void>
- struct is_lambda_type : std::false_type
- {
- };
- // check if operator() is available
- template <class E>
- struct is_lambda_type<E, msvc2015_void_t<decltype(&E::operator())>> : std::true_type
- {
- };
- template <class T>
- struct self_type
- {
- using type = T;
- };
- template <class CP, class A, class O>
- struct get_buffer_storage
- {
- using type = xtl::mpl::eval_if_t<
- is_lambda_type<A>,
- self_type<xbuffer_smart_pointer<CP, A>>,
- self_type<xbuffer_storage<CP, A>>>;
- };
- template <class CP, class A>
- struct get_buffer_storage<CP, A, acquire_ownership>
- {
- using type = xbuffer_owner_storage<CP, A>;
- };
- template <class CP, class T>
- struct get_buffer_storage<CP, std::shared_ptr<T>, no_ownership>
- {
- using type = xbuffer_smart_pointer<CP, std::shared_ptr<T>>;
- };
- template <class CP, class T>
- struct get_buffer_storage<CP, std::unique_ptr<T>, no_ownership>
- {
- using type = xbuffer_smart_pointer<CP, std::unique_ptr<T>>;
- };
- template <class CP, class A, class O>
- using buffer_storage_t = typename get_buffer_storage<CP, A, O>::type;
- }
- /************************
- * xbuffer_adaptor_base *
- ************************/
- template <class D>
- struct buffer_inner_types;
- template <class D>
- class xbuffer_adaptor_base
- {
- public:
- using self_type = xbuffer_adaptor_base<D>;
- using derived_type = D;
- using inner_types = buffer_inner_types<D>;
- using value_type = typename inner_types::value_type;
- using reference = typename inner_types::reference;
- using const_reference = typename inner_types::const_reference;
- using pointer = typename inner_types::pointer;
- using const_pointer = typename inner_types::const_pointer;
- using size_type = typename inner_types::size_type;
- using difference_type = typename inner_types::difference_type;
- using iterator = typename inner_types::iterator;
- using const_iterator = typename inner_types::const_iterator;
- using reverse_iterator = typename inner_types::reverse_iterator;
- using const_reverse_iterator = typename inner_types::const_reverse_iterator;
- using index_type = typename inner_types::index_type;
- bool empty() const noexcept;
- reference operator[](size_type i);
- const_reference operator[](size_type i) const;
- reference front();
- const_reference front() const;
- reference back();
- const_reference back() const;
- iterator begin() noexcept;
- iterator end() noexcept;
- const_iterator begin() const noexcept;
- const_iterator end() const noexcept;
- const_iterator cbegin() const noexcept;
- const_iterator cend() const noexcept;
- reverse_iterator rbegin() noexcept;
- reverse_iterator rend() noexcept;
- const_reverse_iterator rbegin() const noexcept;
- const_reverse_iterator rend() const noexcept;
- const_reverse_iterator crbegin() const noexcept;
- const_reverse_iterator crend() const noexcept;
- derived_type& derived_cast() noexcept;
- const derived_type& derived_cast() const noexcept;
- protected:
- xbuffer_adaptor_base() = default;
- ~xbuffer_adaptor_base() = default;
- xbuffer_adaptor_base(const self_type&) = default;
- self_type& operator=(const self_type&) = default;
- xbuffer_adaptor_base(self_type&&) = default;
- self_type& operator=(self_type&&) = default;
- };
- template <class D>
- bool operator==(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- template <class D>
- bool operator!=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- template <class D>
- bool operator<(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- template <class D>
- bool operator<=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- template <class D>
- bool operator>(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- template <class D>
- bool operator>=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs);
- /*******************
- * xbuffer_adaptor *
- *******************/
- template <class CP, class O, class A>
- struct buffer_inner_types<xbuffer_adaptor<CP, O, A>>
- {
- using base_type = detail::buffer_storage_t<CP, A, O>;
- using value_type = typename base_type::value_type;
- using reference = typename base_type::reference;
- using const_reference = typename base_type::const_reference;
- using pointer = typename base_type::pointer;
- using const_pointer = typename base_type::const_pointer;
- using size_type = typename base_type::size_type;
- using difference_type = typename base_type::difference_type;
- using iterator = pointer;
- using const_iterator = const_pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using index_type = size_type;
- };
- template <class CP, class O, class A>
- class xbuffer_adaptor : private detail::buffer_storage_t<CP, A, O>,
- public xbuffer_adaptor_base<xbuffer_adaptor<CP, O, A>>
- {
- public:
- using self_type = xbuffer_adaptor<CP, O, A>;
- using base_type = detail::buffer_storage_t<CP, A, O>;
- using buffer_base_type = xbuffer_adaptor_base<self_type>;
- using allocator_type = typename base_type::allocator_type;
- using destructor_type = typename base_type::destructor_type;
- using value_type = typename buffer_base_type::value_type;
- using reference = typename buffer_base_type::reference;
- using const_reference = typename buffer_base_type::const_reference;
- using pointer = typename buffer_base_type::pointer;
- using const_pointer = typename buffer_base_type::const_pointer;
- using size_type = typename buffer_base_type::size_type;
- using difference_type = typename buffer_base_type::difference_type;
- using iterator = typename buffer_base_type::iterator;
- using const_iterator = typename buffer_base_type::const_iterator;
- using reverse_iterator = typename buffer_base_type::reverse_iterator;
- using const_reverse_iterator = typename buffer_base_type::const_reverse_iterator;
- using temporary_type = uvector<value_type, allocator_type>;
- xbuffer_adaptor() = default;
- using base_type::base_type;
- ~xbuffer_adaptor() = default;
- xbuffer_adaptor(const self_type&) = default;
- self_type& operator=(const self_type&) = default;
- xbuffer_adaptor(self_type&&) = default;
- xbuffer_adaptor& operator=(self_type&&) = default;
- self_type& operator=(temporary_type&&);
- using base_type::data;
- using base_type::reset_data;
- using base_type::resize;
- using base_type::size;
- using base_type::swap;
- };
- template <class CP, class O, class A>
- void swap(xbuffer_adaptor<CP, O, A>& lhs, xbuffer_adaptor<CP, O, A>& rhs) noexcept;
- /*********************
- * xiterator_adaptor *
- *********************/
- template <class I, class CI>
- class xiterator_adaptor;
- template <class I, class CI>
- struct buffer_inner_types<xiterator_adaptor<I, CI>>
- {
- using traits = std::iterator_traits<I>;
- using const_traits = std::iterator_traits<CI>;
- using value_type = std::common_type_t<typename traits::value_type, typename const_traits::value_type>;
- using reference = typename traits::reference;
- using const_reference = typename const_traits::reference;
- using pointer = typename traits::pointer;
- using const_pointer = typename const_traits::pointer;
- using difference_type = std::common_type_t<typename traits::difference_type, typename const_traits::difference_type>;
- using size_type = std::make_unsigned_t<difference_type>;
- using iterator = I;
- using const_iterator = CI;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using index_type = difference_type;
- };
- template <class I, class CI>
- class xiterator_adaptor : public xbuffer_adaptor_base<xiterator_adaptor<I, CI>>
- {
- public:
- using self_type = xiterator_adaptor<I, CI>;
- using base_type = xbuffer_adaptor_base<self_type>;
- using value_type = typename base_type::value_type;
- using allocator_type = std::allocator<value_type>;
- using size_type = typename base_type::size_type;
- using iterator = typename base_type::iterator;
- using const_iterator = typename base_type::const_iterator;
- using temporary_type = uvector<value_type, allocator_type>;
- xiterator_adaptor() = default;
- xiterator_adaptor(I it, CI cit, size_type size);
- ~xiterator_adaptor() = default;
- xiterator_adaptor(const self_type&) = default;
- xiterator_adaptor& operator=(const self_type&) = default;
- xiterator_adaptor(self_type&&) = default;
- xiterator_adaptor& operator=(self_type&&) = default;
- xiterator_adaptor& operator=(const temporary_type& rhs);
- xiterator_adaptor& operator=(temporary_type&& rhs);
- size_type size() const noexcept;
- void resize(size_type size);
- iterator data() noexcept;
- const_iterator data() const noexcept;
- void swap(self_type& rhs) noexcept;
- private:
- I m_it;
- CI m_cit;
- size_type m_size;
- };
- template <class I, class CI>
- void swap(xiterator_adaptor<I, CI>& lhs, xiterator_adaptor<I, CI>& rhs) noexcept;
- template <class I, class CI>
- struct is_contiguous_container<xiterator_adaptor<I, CI>> : is_contiguous_container<I>
- {
- };
- /***************************
- * xiterator_owner_adaptor *
- ***************************/
- template <class C, class IG>
- class xiterator_owner_adaptor;
- template <class C, class IG>
- struct buffer_inner_types<xiterator_owner_adaptor<C, IG>>
- {
- using iterator = typename IG::iterator;
- using const_iterator = typename IG::const_iterator;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- using traits = std::iterator_traits<iterator>;
- using const_traits = std::iterator_traits<const_iterator>;
- using value_type = std::common_type_t<typename traits::value_type, typename const_traits::value_type>;
- using reference = typename traits::reference;
- using const_reference = typename const_traits::reference;
- using pointer = typename traits::pointer;
- using const_pointer = typename const_traits::pointer;
- using difference_type = std::common_type_t<typename traits::difference_type, typename const_traits::difference_type>;
- using size_type = std::make_unsigned_t<difference_type>;
- using index_type = difference_type;
- };
- template <class C, class IG>
- class xiterator_owner_adaptor : public xbuffer_adaptor_base<xiterator_owner_adaptor<C, IG>>
- {
- public:
- using self_type = xiterator_owner_adaptor<C, IG>;
- using base_type = xbuffer_adaptor_base<self_type>;
- using value_type = typename base_type::value_type;
- using allocator_type = std::allocator<value_type>;
- using size_type = typename base_type::size_type;
- using iterator = typename base_type::iterator;
- using const_iterator = typename base_type::const_iterator;
- using temporary_type = uvector<value_type, allocator_type>;
- xiterator_owner_adaptor(C&& c);
- ~xiterator_owner_adaptor() = default;
- xiterator_owner_adaptor(const self_type&);
- xiterator_owner_adaptor& operator=(const self_type&);
- xiterator_owner_adaptor(self_type&&);
- xiterator_owner_adaptor& operator=(self_type&&);
- xiterator_owner_adaptor& operator=(const temporary_type& rhs);
- xiterator_owner_adaptor& operator=(temporary_type&& rhs);
- size_type size() const noexcept;
- void resize(size_type size);
- iterator data() noexcept;
- const_iterator data() const noexcept;
- void swap(self_type& rhs) noexcept;
- private:
- void init_iterators();
- C m_container;
- iterator m_it;
- const_iterator m_cit;
- size_type m_size;
- };
- template <class C, class IG>
- void swap(xiterator_owner_adaptor<C, IG>& lhs, xiterator_owner_adaptor<C, IG>& rhs) noexcept;
- template <class C, class IG>
- struct is_contiguous_container<xiterator_owner_adaptor<C, IG>>
- : is_contiguous_container<typename IG::iterator>
- {
- };
- /**************************
- * make_xiterator_adaptor *
- **************************/
- template <class C, class IG>
- auto make_xiterator_adaptor(C&& container, IG iterator_getter);
- /************************************
- * temporary_container metafunction *
- ************************************/
- template <class C>
- struct temporary_container
- {
- using type = C;
- };
- template <class CP, class O, class A>
- struct temporary_container<xbuffer_adaptor<CP, O, A>>
- {
- using type = typename xbuffer_adaptor<CP, O, A>::temporary_type;
- };
- template <class I, class CI>
- struct temporary_container<xiterator_adaptor<I, CI>>
- {
- using type = typename xiterator_adaptor<I, CI>::temporary_type;
- };
- template <class C, class IG>
- struct temporary_container<xiterator_owner_adaptor<C, IG>>
- {
- using type = typename xiterator_owner_adaptor<C, IG>::temporary_type;
- };
- template <class C>
- using temporary_container_t = typename temporary_container<C>::type;
- /**********************************
- * xbuffer_storage implementation *
- **********************************/
- namespace detail
- {
- template <class CP, class A>
- inline xbuffer_storage<CP, A>::xbuffer_storage()
- : p_data(nullptr)
- , m_size(0)
- {
- }
- template <class CP, class A>
- template <class P>
- inline xbuffer_storage<CP, A>::xbuffer_storage(P&& data, size_type size, const allocator_type&)
- : p_data(std::forward<P>(data))
- , m_size(size)
- {
- }
- template <class CP, class A>
- inline auto xbuffer_storage<CP, A>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class CP, class A>
- inline void xbuffer_storage<CP, A>::resize(size_type size)
- {
- if (size != m_size)
- {
- XTENSOR_THROW(std::runtime_error, "xbuffer_storage not resizable");
- }
- }
- template <class CP, class A>
- inline auto xbuffer_storage<CP, A>::data() noexcept -> pointer
- {
- return p_data;
- }
- template <class CP, class A>
- inline auto xbuffer_storage<CP, A>::data() const noexcept -> const_pointer
- {
- return p_data;
- }
- template <class CP, class A>
- inline void xbuffer_storage<CP, A>::swap(self_type& rhs) noexcept
- {
- using std::swap;
- swap(p_data, rhs.p_data);
- swap(m_size, rhs.m_size);
- }
- template <class CP, class A>
- template <class P>
- inline void xbuffer_storage<CP, A>::reset_data(P&& data, size_type size) noexcept
- {
- p_data = std::forward<P>(data);
- m_size = size;
- }
- }
- /****************************************
- * xbuffer_owner_storage implementation *
- ****************************************/
- namespace detail
- {
- template <class CP, class A>
- template <class P>
- inline xbuffer_owner_storage<CP, A>::xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc)
- : m_data(std::forward<P>(data))
- , m_size(size)
- , m_moved_from(false)
- , m_allocator(alloc)
- {
- }
- template <class CP, class A>
- inline xbuffer_owner_storage<CP, A>::~xbuffer_owner_storage()
- {
- if (!m_moved_from)
- {
- safe_destroy_deallocate(m_allocator, m_data.get(), m_size);
- m_size = 0;
- }
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::operator=(const self_type& rhs) -> self_type&
- {
- using std::swap;
- if (this != &rhs)
- {
- allocator_type al = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
- rhs.get_allocator()
- );
- pointer tmp = safe_init_allocate(al, rhs.m_size);
- if (xtrivially_default_constructible<value_type>::value)
- {
- std::uninitialized_copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp);
- }
- else
- {
- std::copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp);
- }
- swap(m_data.get(), tmp);
- swap(m_allocator, al);
- safe_destroy_deallocate(al, tmp, m_size);
- m_size = rhs.m_size;
- }
- return *this;
- }
- template <class CP, class A>
- inline xbuffer_owner_storage<CP, A>::xbuffer_owner_storage(self_type&& rhs)
- : m_data(std::move(rhs.m_data))
- , m_size(std::move(rhs.m_size))
- , m_moved_from(std::move(rhs.m_moved_from))
- , m_allocator(std::move(rhs.m_allocator))
- {
- rhs.m_moved_from = true;
- rhs.m_size = 0;
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::operator=(self_type&& rhs) -> self_type&
- {
- swap(rhs);
- return *this;
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class CP, class A>
- void xbuffer_owner_storage<CP, A>::resize(size_type size)
- {
- using std::swap;
- if (size != m_size)
- {
- pointer tmp = safe_init_allocate(m_allocator, size);
- swap(m_data.get(), tmp);
- swap(m_size, size);
- safe_destroy_deallocate(m_allocator, tmp, size);
- }
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::data() noexcept -> pointer
- {
- return m_data.get();
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::data() const noexcept -> const_pointer
- {
- return m_data.get();
- }
- template <class CP, class A>
- inline auto xbuffer_owner_storage<CP, A>::get_allocator() const noexcept -> allocator_type
- {
- return allocator_type(m_allocator);
- }
- template <class CP, class A>
- inline void xbuffer_owner_storage<CP, A>::swap(self_type& rhs) noexcept
- {
- using std::swap;
- swap(m_data, rhs.m_data);
- swap(m_size, rhs.m_size);
- swap(m_allocator, rhs.m_allocator);
- }
- template <class CP, class A>
- template <class P>
- inline void
- xbuffer_owner_storage<CP, A>::reset_data(P&& data, size_type size, const allocator_type& alloc) noexcept
- {
- xbuffer_owner_storage<CP, A> tmp(std::forward<P>(data), size, alloc);
- this->swap(tmp);
- }
- }
- /****************************************
- * xbuffer_smart_pointer implementation *
- ****************************************/
- namespace detail
- {
- template <class CP, class D>
- template <class P, class DT>
- xbuffer_smart_pointer<CP, D>::xbuffer_smart_pointer(P&& data_ptr, size_type size, DT&& destruct)
- : p_data(data_ptr)
- , m_size(size)
- , m_destruct(std::forward<DT>(destruct))
- {
- }
- template <class CP, class D>
- auto xbuffer_smart_pointer<CP, D>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class CP, class D>
- void xbuffer_smart_pointer<CP, D>::resize(size_type size)
- {
- if (m_size != size)
- {
- XTENSOR_THROW(std::runtime_error, "xbuffer_storage not resizeable");
- }
- }
- template <class CP, class D>
- auto xbuffer_smart_pointer<CP, D>::data() noexcept -> pointer
- {
- return p_data;
- }
- template <class CP, class D>
- auto xbuffer_smart_pointer<CP, D>::data() const noexcept -> const_pointer
- {
- return p_data;
- }
- template <class CP, class D>
- void xbuffer_smart_pointer<CP, D>::swap(self_type& rhs) noexcept
- {
- using std::swap;
- swap(p_data, rhs.p_data);
- swap(m_size, rhs.m_size);
- swap(m_destruct, rhs.m_destruct);
- }
- template <class CP, class D>
- template <class P, class DT>
- void xbuffer_smart_pointer<CP, D>::reset_data(P&& data, size_type size, DT&& destruct) noexcept
- {
- p_data = std::forward<P>(data);
- m_size = size;
- m_destruct = destruct;
- }
- }
- /***************************************
- * xbuffer_adaptor_base implementation *
- ***************************************/
- template <class D>
- inline bool xbuffer_adaptor_base<D>::empty() const noexcept
- {
- return derived_cast().size() == size_type(0);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::operator[](size_type i) -> reference
- {
- return derived_cast().data()[static_cast<index_type>(i)];
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::operator[](size_type i) const -> const_reference
- {
- return derived_cast().data()[static_cast<index_type>(i)];
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::front() -> reference
- {
- return this->operator[](0);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::front() const -> const_reference
- {
- return this->operator[](0);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::back() -> reference
- {
- return this->operator[](derived_cast().size() - 1);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::back() const -> const_reference
- {
- return this->operator[](derived_cast().size() - 1);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::begin() noexcept -> iterator
- {
- return derived_cast().data();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::end() noexcept -> iterator
- {
- return derived_cast().data() + static_cast<index_type>(derived_cast().size());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::begin() const noexcept -> const_iterator
- {
- return derived_cast().data();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::end() const noexcept -> const_iterator
- {
- return derived_cast().data() + static_cast<index_type>(derived_cast().size());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::cbegin() const noexcept -> const_iterator
- {
- return begin();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::cend() const noexcept -> const_iterator
- {
- return end();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::rbegin() noexcept -> reverse_iterator
- {
- return reverse_iterator(end());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::rend() noexcept -> reverse_iterator
- {
- return reverse_iterator(begin());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::rbegin() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator(end());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::rend() const noexcept -> const_reverse_iterator
- {
- return const_reverse_iterator(begin());
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::crbegin() const noexcept -> const_reverse_iterator
- {
- return rbegin();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::crend() const noexcept -> const_reverse_iterator
- {
- return rend();
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::derived_cast() noexcept -> derived_type&
- {
- return *static_cast<derived_type*>(this);
- }
- template <class D>
- inline auto xbuffer_adaptor_base<D>::derived_cast() const noexcept -> const derived_type&
- {
- return *static_cast<const derived_type*>(this);
- }
- template <class D>
- inline bool operator==(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return lhs.derived_cast().size() == rhs.derived_cast().size()
- && std::equal(lhs.begin(), lhs.end(), rhs.begin());
- }
- template <class D>
- inline bool operator!=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return !(lhs == rhs);
- }
- template <class D>
- inline bool operator<(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return std::lexicographical_compare(
- lhs.begin(),
- lhs.end(),
- rhs.begin(),
- rhs.end(),
- std::less<typename D::value_type>()
- );
- }
- template <class D>
- inline bool operator<=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return std::lexicographical_compare(
- lhs.begin(),
- lhs.end(),
- rhs.begin(),
- rhs.end(),
- std::less_equal<typename D::value_type>()
- );
- }
- template <class D>
- inline bool operator>(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return std::lexicographical_compare(
- lhs.begin(),
- lhs.end(),
- rhs.begin(),
- rhs.end(),
- std::greater<typename D::value_type>()
- );
- }
- template <class D>
- inline bool operator>=(const xbuffer_adaptor_base<D>& lhs, const xbuffer_adaptor_base<D>& rhs)
- {
- return std::lexicographical_compare(
- lhs.begin(),
- lhs.end(),
- rhs.begin(),
- rhs.end(),
- std::greater_equal<typename D::value_type>()
- );
- }
- /**********************************
- * xbuffer_adaptor implementation *
- **********************************/
- template <class CP, class O, class A>
- inline auto xbuffer_adaptor<CP, O, A>::operator=(temporary_type&& tmp) -> self_type&
- {
- base_type::resize(tmp.size());
- std::copy(tmp.cbegin(), tmp.cend(), this->begin());
- return *this;
- }
- template <class CP, class O, class A>
- inline void swap(xbuffer_adaptor<CP, O, A>& lhs, xbuffer_adaptor<CP, O, A>& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- /************************************
- * xiterator_adaptor implementation *
- ************************************/
- template <class I, class CI>
- inline xiterator_adaptor<I, CI>::xiterator_adaptor(I it, CI cit, size_type size)
- : m_it(it)
- , m_cit(cit)
- , m_size(size)
- {
- }
- template <class I, class CI>
- inline auto xiterator_adaptor<I, CI>::operator=(const temporary_type& rhs) -> self_type&
- {
- resize(rhs.size());
- std::copy(rhs.cbegin(), rhs.cend(), m_it);
- return *this;
- }
- template <class I, class CI>
- inline auto xiterator_adaptor<I, CI>::operator=(temporary_type&& rhs) -> self_type&
- {
- return (*this = rhs);
- }
- template <class I, class CI>
- inline auto xiterator_adaptor<I, CI>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class I, class CI>
- inline void xiterator_adaptor<I, CI>::resize(size_type size)
- {
- if (m_size != size)
- {
- XTENSOR_THROW(std::runtime_error, "xiterator_adaptor not resizeable");
- }
- }
- template <class I, class CI>
- inline auto xiterator_adaptor<I, CI>::data() noexcept -> iterator
- {
- return m_it;
- }
- template <class I, class CI>
- inline auto xiterator_adaptor<I, CI>::data() const noexcept -> const_iterator
- {
- return m_cit;
- }
- template <class I, class CI>
- inline void xiterator_adaptor<I, CI>::swap(self_type& rhs) noexcept
- {
- using std::swap;
- swap(m_it, rhs.m_it);
- swap(m_cit, rhs.m_cit);
- swap(m_size, rhs.m_size);
- }
- template <class I, class CI>
- inline void swap(xiterator_adaptor<I, CI>& lhs, xiterator_adaptor<I, CI>& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- /******************************************
- * xiterator_owner_adaptor implementation *
- ******************************************/
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>::xiterator_owner_adaptor(C&& c)
- : m_container(std::move(c))
- {
- init_iterators();
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>::xiterator_owner_adaptor(const self_type& rhs)
- : m_container(rhs.m_container)
- {
- init_iterators();
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>& xiterator_owner_adaptor<C, IG>::operator=(const self_type& rhs)
- {
- m_container = rhs.m_container;
- init_iterators();
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>::xiterator_owner_adaptor(self_type&& rhs)
- : m_container(std::move(rhs.m_container))
- {
- init_iterators();
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>& xiterator_owner_adaptor<C, IG>::operator=(self_type&& rhs)
- {
- m_container = std::move(rhs.m_container);
- init_iterators();
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>& xiterator_owner_adaptor<C, IG>::operator=(const temporary_type& rhs)
- {
- resize(rhs.size());
- std::copy(rhs.cbegin(), rhs.cend(), m_it);
- return *this;
- }
- template <class C, class IG>
- inline xiterator_owner_adaptor<C, IG>& xiterator_owner_adaptor<C, IG>::operator=(temporary_type&& rhs)
- {
- return (*this = rhs);
- }
- template <class C, class IG>
- inline auto xiterator_owner_adaptor<C, IG>::size() const noexcept -> size_type
- {
- return m_size;
- }
- template <class C, class IG>
- inline void xiterator_owner_adaptor<C, IG>::resize(size_type size)
- {
- if (m_size != size)
- {
- XTENSOR_THROW(std::runtime_error, "xiterator_owner_adaptor not resizeable");
- }
- }
- template <class C, class IG>
- inline auto xiterator_owner_adaptor<C, IG>::data() noexcept -> iterator
- {
- return m_it;
- }
- template <class C, class IG>
- inline auto xiterator_owner_adaptor<C, IG>::data() const noexcept -> const_iterator
- {
- return m_cit;
- }
- template <class C, class IG>
- inline void xiterator_owner_adaptor<C, IG>::swap(self_type& rhs) noexcept
- {
- using std::swap;
- swap(m_container, rhs.m_container);
- init_iterators();
- rhs.init_iterators();
- }
- template <class C, class IG>
- inline void xiterator_owner_adaptor<C, IG>::init_iterators()
- {
- m_it = IG::begin(m_container);
- m_cit = IG::cbegin(m_container);
- m_size = IG::size(m_container);
- }
- template <class C, class IG>
- inline void swap(xiterator_owner_adaptor<C, IG>& lhs, xiterator_owner_adaptor<C, IG>& rhs) noexcept
- {
- lhs.swap(rhs);
- }
- /*****************************************
- * make_xiterator_adaptor implementation *
- *****************************************/
- namespace detail
- {
- template <class C, class IG, bool = std::is_lvalue_reference<C>::value>
- struct xiterator_adaptor_builder
- {
- using iterator = decltype(IG::begin(std::declval<C>()));
- using const_iterator = decltype(IG::cbegin(std::declval<C>()));
- using type = xiterator_adaptor<iterator, const_iterator>;
- inline static type build(C& c)
- {
- return type(IG::begin(c), IG::cbegin(c), IG::size(c));
- }
- };
- template <class C, class IG>
- struct xiterator_adaptor_builder<C, IG, false>
- {
- using type = xiterator_owner_adaptor<C, IG>;
- inline static type build(C&& c)
- {
- return type(std::move(c));
- }
- };
- }
- template <class C, class IG>
- inline auto make_xiterator_adaptor(C&& container, IG)
- {
- using builder_type = detail::xiterator_adaptor_builder<C, IG>;
- return builder_type::build(std::forward<C>(container));
- }
- }
- #endif
|