/* Copyright 2024 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org/libs/poly_collection for library home page. */ #ifndef BOOST_POLY_COLLECTION_DETAIL_FIXED_VARIANT_ITERATOR_HPP #define BOOST_POLY_COLLECTION_DETAIL_FIXED_VARIANT_ITERATOR_HPP #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include namespace boost{ namespace poly_collection{ namespace detail{ /* Iterator over the sequence of T subojects within a range of * fixed_variant_closure>s. */ template class fixed_variant_alternative_iterator: public boost::iterator_facade< fixed_variant_alternative_iterator, T, boost::random_access_traversal_tag > { static constexpr std::size_t Stride=sizeof( fixed_variant_impl::fixed_variant_closure< typename std::remove_const::type,Variant>); public: fixed_variant_alternative_iterator()=default; fixed_variant_alternative_iterator(T* p)noexcept:p{p}{} fixed_variant_alternative_iterator( const fixed_variant_alternative_iterator&)=default; fixed_variant_alternative_iterator& operator=( const fixed_variant_alternative_iterator&)=default; template< typename NonConstT, typename std::enable_if< std::is_same::value>::type* =nullptr > fixed_variant_alternative_iterator( const fixed_variant_alternative_iterator& x)noexcept: p{x.p}{} template< typename NonConstT, typename std::enable_if< std::is_same::value>::type* =nullptr > fixed_variant_alternative_iterator& operator=( const fixed_variant_alternative_iterator& x)noexcept { p=x.p; return *this; } /* interoperability with T* */ fixed_variant_alternative_iterator& operator=(T* p_)noexcept {p=p_;return *this;} operator T*()const noexcept{return p;} std::size_t stride()const noexcept{return Stride;} private: template friend class fixed_variant_alternative_iterator; using char_pointer=typename std::conditional< std::is_const::value, const char*, char* >::type; static char_pointer char_ptr(T* p)noexcept {return reinterpret_cast(p);} static T* value_ptr(char_pointer p)noexcept {return reinterpret_cast(p);} friend class boost::iterator_core_access; T& dereference()const noexcept{return *p;} bool equal(const fixed_variant_alternative_iterator& x)const noexcept {return p==x.p;} void increment()noexcept{p=value_ptr(char_ptr(p)+Stride);} void decrement()noexcept{p=value_ptr(char_ptr(p)-Stride);} template void advance(Integral n)noexcept {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)Stride);} std::ptrdiff_t distance_to( const fixed_variant_alternative_iterator& x)const noexcept {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)Stride;} T* p; }; /* Iterator over the sequence of fixed_variant base objects within a range of * fixed_variant_closure>s. As T is not part of the * iterator definition, the stride between values is a run-time value. */ template class fixed_variant_iterator: public boost::iterator_facade< fixed_variant_iterator, Variant, boost::random_access_traversal_tag > { public: fixed_variant_iterator()=default; fixed_variant_iterator(Variant* p,std::size_t stride)noexcept: p{p},stride_{stride}{} fixed_variant_iterator(const fixed_variant_iterator&)=default; fixed_variant_iterator& operator=(const fixed_variant_iterator&)=default; template< typename NonConstVariant, typename std::enable_if< std::is_same::value>::type* =nullptr > fixed_variant_iterator( const fixed_variant_iterator& x)noexcept: p{x.p},stride_{x.stride_}{} template< typename NonConstVariant, typename std::enable_if< std::is_same::value>::type* =nullptr > fixed_variant_iterator& operator=( const fixed_variant_iterator& x)noexcept { p=x.p;stride_=x.stride_; return *this; } /* interoperability with Variant* */ fixed_variant_iterator& operator=(Variant* p_)noexcept{p=p_;return *this;} operator Variant*()const noexcept{return p;} /* interoperability with fixed_variant_alternative_iterator */ #include template< typename T, typename NonConstT=typename std::remove_const::type, typename NonConstVariant=typename std::remove_const::type, typename std::enable_if< mp11::mp_contains::value&& (!std::is_const::value||std::is_const::value) >::type* =nullptr > BOOST_POLY_COLLECTION_NO_SANITIZE explicit operator fixed_variant_alternative_iterator()const noexcept { return p?std::addressof(unsafe_get(*p)):nullptr; } #include std::size_t stride()const noexcept{return stride_;} private: template friend class fixed_variant_iterator; using char_pointer=typename std::conditional< std::is_const::value, const char*, char* >::type; static char_pointer char_ptr(Variant* p)noexcept {return reinterpret_cast(p);} static Variant* value_ptr(char_pointer p)noexcept {return reinterpret_cast(p);} friend class boost::iterator_core_access; Variant& dereference()const noexcept{return *p;} bool equal(const fixed_variant_iterator& x)const noexcept{return p==x.p;} void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);} void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);} template void advance(Integral n)noexcept {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)stride_);} std::ptrdiff_t distance_to(const fixed_variant_iterator& x)const noexcept {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)stride_;} Variant* p; std::size_t stride_; }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif