Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:47:50

0001 /* Copyright 2016-2019 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/iterator/iterator_facade.hpp>
0018 #include <type_traits>
0019 
0020 namespace boost{
0021 
0022 namespace poly_collection{
0023 
0024 namespace detail{
0025 
0026 /* random-access iterator to Value elements laid out stride *chars* apart */
0027 
0028 template<typename Value>
0029 class stride_iterator:
0030   public boost::iterator_facade<
0031     stride_iterator<Value>,
0032     Value,
0033     boost::random_access_traversal_tag
0034   >
0035 {
0036 public:
0037   stride_iterator()=default;
0038   stride_iterator(Value* p,std::size_t stride)noexcept:p{p},stride_{stride}{}
0039   stride_iterator(const stride_iterator&)=default;
0040   stride_iterator& operator=(const stride_iterator&)=default;
0041 
0042   template<
0043     typename NonConstValue,
0044     typename std::enable_if<
0045       std::is_same<Value,const NonConstValue>::value>::type* =nullptr
0046   >
0047   stride_iterator(const stride_iterator<NonConstValue>& x)noexcept:
0048     p{x.p},stride_{x.stride_}{}
0049 
0050   template<
0051     typename NonConstValue,
0052     typename std::enable_if<
0053       std::is_same<Value,const NonConstValue>::value>::type* =nullptr
0054   >
0055   stride_iterator& operator=(const stride_iterator<NonConstValue>& x)noexcept
0056   {
0057     p=x.p;stride_=x.stride_;
0058     return *this;
0059   }
0060 
0061   /* interoperability with [Derived]Value* */
0062 
0063   stride_iterator& operator=(Value* p_)noexcept{p=p_;return *this;}
0064   operator Value*()const noexcept{return p;}
0065 
0066   template<
0067     typename DerivedValue,
0068     typename std::enable_if<
0069       std::is_base_of<Value,DerivedValue>::value&&
0070       (std::is_const<Value>::value||!std::is_const<DerivedValue>::value)
0071     >::type* =nullptr
0072   >
0073   explicit stride_iterator(DerivedValue* x)noexcept:
0074     p{x},stride_{sizeof(DerivedValue)}{}
0075 
0076 #if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=40900)||\
0077     BOOST_WORKAROUND(BOOST_CLANG,>=1)&&\
0078     (__clang_major__>3 || __clang_major__==3 && __clang_minor__ >= 8)
0079 /* https://github.com/boostorg/poly_collection/issues/15 */
0080   
0081 #define BOOST_POLY_COLLECTION_NO_SANITIZE
0082 
0083 /* UBSan seems not to be supported in some environments */
0084 #if defined(BOOST_GCC_VERSION)
0085 #pragma GCC diagnostic push
0086 #pragma GCC diagnostic ignored "-Wattributes"
0087 #elif defined(BOOST_CLANG)
0088 #pragma clang diagnostic push
0089 #pragma clang diagnostic ignored "-Wattributes"
0090 #endif
0091 #endif
0092 
0093   template<
0094     typename DerivedValue,
0095     typename std::enable_if<
0096       std::is_base_of<Value,DerivedValue>::value&&
0097       (!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
0098     >::type* =nullptr
0099   >
0100 #if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
0101   __attribute__((no_sanitize("undefined")))
0102 #endif
0103   explicit operator DerivedValue*()const noexcept
0104   {return static_cast<DerivedValue*>(p);}
0105 
0106 #if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
0107 #if defined(BOOST_GCC_VERSION)
0108 #pragma GCC diagnostic pop
0109 #elif defined(BOOST_CLANG)
0110 #pragma clang diagnostic pop
0111 #endif
0112 
0113 #undef BOOST_POLY_COLLECTION_NO_SANITIZE
0114 #endif
0115 
0116   std::size_t stride()const noexcept{return stride_;}
0117 
0118 private:
0119   template<typename>
0120   friend class stride_iterator;
0121 
0122   using char_pointer=typename std::conditional<
0123     std::is_const<Value>::value,
0124     const char*,
0125     char*
0126   >::type;
0127 
0128   static char_pointer char_ptr(Value* p)noexcept
0129     {return reinterpret_cast<char_pointer>(p);}
0130   static Value*       value_ptr(char_pointer p)noexcept
0131     {return reinterpret_cast<Value*>(p);}
0132 
0133   friend class boost::iterator_core_access;
0134 
0135   Value& dereference()const noexcept{return *p;}
0136   bool equal(const stride_iterator& x)const noexcept{return p==x.p;}
0137   void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);}
0138   void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);}
0139   template<typename Integral>
0140   void advance(Integral n)noexcept
0141     {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)stride_);}
0142   std::ptrdiff_t distance_to(const stride_iterator& x)const noexcept
0143     {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)stride_;}          
0144 
0145   Value*      p;
0146   std::size_t stride_;
0147 };
0148 
0149 } /* namespace poly_collection::detail */
0150 
0151 } /* namespace poly_collection */
0152 
0153 } /* namespace boost */
0154 
0155 #endif