1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- 2 // 3 // VectorBase.h: Rcpp R/C++ interface class library -- 4 // 5 // Copyright (C) 2010 - 2013 Dirk Eddelbuettel and Romain Francois 6 // 7 // This file is part of Rcpp. 8 // 9 // Rcpp is free software: you can redistribute it and/or modify it 10 // under the terms of the GNU General Public License as published by 11 // the Free Software Foundation, either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Rcpp is distributed in the hope that it will be useful, but 15 // WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 21 22 #ifndef Rcpp__vector__VectorBase_h 23 #define Rcpp__vector__VectorBase_h 24 25 namespace Rcpp{ 26 27 /** a base class for vectors, modelled after the CRTP */ 28 template <int RTYPE, bool na, typename VECTOR> 29 class VectorBase : public traits::expands_to_logical__impl<RTYPE> { 30 public: 31 struct rcpp_sugar_expression{} ; 32 struct r_type : traits::integral_constant<int,RTYPE>{} ; 33 struct can_have_na : traits::integral_constant<bool,na>{} ; 34 typedef typename traits::storage_type<RTYPE>::type stored_type ; 35 typedef typename traits::storage_type<RTYPE>::type elem_type ; 36 get_ref()37 VECTOR& get_ref(){ 38 return static_cast<VECTOR&>(*this) ; 39 } 40 get_ref()41 const VECTOR& get_ref() const { 42 return static_cast<const VECTOR&>(*this) ; 43 } 44 45 inline stored_type operator[]( R_xlen_t i) const { 46 return static_cast<const VECTOR*>(this)->operator[](i) ; 47 } 48 size()49 inline R_xlen_t size() const { return static_cast<const VECTOR*>(this)->size() ; } 50 51 // We now have the structure to correct const-correctness, but without 52 // major changes to the proxy mechanism, we cannot do it correctly. As 53 // a result, it turns out that both Vector iterators are effectively 54 // const, but this has always been the way it is so we won't break any 55 // compatibility. TODO: Fix proxies and make this const correct. 56 struct iter_traits 57 { 58 typedef stored_type & reference ; 59 typedef stored_type* pointer ; 60 typedef R_xlen_t difference_type ; 61 typedef stored_type value_type; 62 typedef std::random_access_iterator_tag iterator_category ; 63 }; 64 65 struct const_iter_traits 66 { 67 typedef stored_type reference ; 68 typedef stored_type const * pointer ; 69 typedef R_xlen_t difference_type ; 70 typedef const stored_type value_type; 71 typedef std::random_access_iterator_tag iterator_category ; 72 }; 73 74 template< typename TRAITS > 75 class iter_base { 76 public: 77 typedef typename TRAITS::reference reference; 78 typedef typename TRAITS::pointer pointer; 79 typedef typename TRAITS::difference_type difference_type; 80 typedef typename TRAITS::value_type value_type; 81 typedef typename TRAITS::iterator_category iterator_category; 82 iter_base(const VectorBase & object_,R_xlen_t index_)83 iter_base( const VectorBase& object_, R_xlen_t index_ ) : object(object_.get_ref()), index(index_){} 84 85 inline iter_base& operator++(){ 86 index++ ; 87 return *this ; 88 } 89 inline iter_base operator++(int){ 90 iterator orig(*this); 91 ++(*this) ; 92 return orig ; 93 } 94 95 inline iter_base& operator--(){ 96 index-- ; 97 return *this ; 98 } 99 inline iter_base operator--(int){ 100 iterator orig(*this); 101 --(*this) ; 102 return orig ; 103 } 104 105 inline iter_base operator+(difference_type n) const { 106 return iterator( object, index+n ) ; 107 } 108 inline iter_base operator-(difference_type n) const { 109 return iterator( object, index-n ) ; 110 } 111 112 inline iter_base& operator+=(difference_type n) { 113 index += n ; 114 return *this ; 115 } 116 inline iter_base& operator-=(difference_type n) { 117 index -= n; 118 return *this ; 119 } 120 121 inline reference operator[](R_xlen_t i){ 122 return object[index+i] ; 123 } 124 125 inline reference operator*() { 126 return object[index] ; 127 } 128 inline pointer operator->(){ 129 return &object[index] ; 130 } 131 132 inline bool operator==( const iter_base& y) const { 133 return ( index == y.index ) ; 134 } 135 inline bool operator!=( const iter_base& y) const { 136 return ( index != y.index ) ; 137 } 138 inline bool operator<( const iter_base& other ) const { 139 return index < other.index ; 140 } 141 inline bool operator>( const iter_base& other ) const { 142 return index > other.index ; 143 } 144 inline bool operator<=( const iter_base& other ) const { 145 return index <= other.index ; 146 } 147 inline bool operator>=( const iter_base& other ) const { 148 return index >= other.index ; 149 } 150 151 inline difference_type operator-(const iter_base& other) const { 152 return index - other.index ; 153 } 154 155 156 private: 157 const VECTOR& object ; 158 R_xlen_t index; 159 } ; 160 161 typedef iter_base< iter_traits > iterator; 162 typedef iter_base< const_iter_traits > const_iterator; 163 begin()164 inline const_iterator begin() const { return const_iterator(*this, 0) ; } end()165 inline const_iterator end() const { return const_iterator(*this, size() ) ; } 166 cbegin()167 inline const_iterator cbegin() const { return const_iterator(*this, 0) ; } cend()168 inline const_iterator cend() const { return const_iterator(*this, size() ) ; } 169 170 } ; 171 172 } // namespace Rcpp 173 #endif 174