开发者

iterator class: compiler error in g++ while doing iterator add or subtract (works in VS2010)

I am implementing an array in C++ (for various reasons, one of them is to get to know custom iterators).

While testing it out I noticed that it does not compile in g++ 4.4 but works fine in Visual Studio 2010.

I have included an example program below. In that, I print out the last but one value of a toy array that I implemented using templates with the accompanying iterator class. The compiler error I get is the following:

$ g++-4.4 -ansi -Wall  -std=c++0x mybuffer.cpp -o mybuffer
In file included from /usr/include/c++/4.4/bits/stl_algobase.h:69,
                 from /usr/include/c++/4.4/memory:49,
                 from mybuffer.cpp:1:
/usr/include/c++/4.4/bits/stl_iterator.h: In member function ‘std::reverse_iterator<_Iterator> std::reverse_iterator<_Iterator>::operator+(typename std::iterator_traits<_Iter>::difference_type) const [with _Iterator = CMyItr<CMyBuff<double>, double>]’:
mybuffer.cpp:205:   instantiated from here
/usr/include/c++/4.4/bits/stl_iterator.h:221: error: passing ‘const CMyItr<CMyBuff<double>, double>’ as ‘this’ argument of ‘CMyItr<T, typename T::value_type> CMyItr<T, elem_type>::operator-(typename T::difference_type) [with T = CMyBuff<double>, elem_type = double]’ discards qualifiers

The error occurs if I do *(RItr+1) operation, not if I do *(++RITr) operation. It works in Visual Studio 2010 in either case however.

I get the same compiler error in g++ 2.95 also. Haven't tried in Visual Studio 6.

Can somebody explain what I am doing wrong and how to fix it?

Thanks. PS: Using g++ 4.6 is a whole another problem, but that is for later.

//-------------------------------------------- example code ----------------//
//------------------------------------------------------------------------------//
//------------------------------------------------------------------------------//
#include <memory> 
#include <iostream>
#include <iterator>
template < typename T, typename elem_type=typename T::value_type> 
               class CMyItr {

public:

  typedef T BuffType;
  typedef CMyItr<T> self_type;
  typedef CMyItr<self_type, elem_type> iterator;
  typedef typename std::bidirectional_iterator_tag iterator_category;
  typedef typename BuffType::value_type value_type;
  typedef typename BuffType::size_type size_type;
  typedef typename BuffType::pointer pointer;
  typedef typename BuffType::const_pointer const_pointer;
  typedef typename BuffType::reference reference;
  typedef typename BuffType::const_reference const_reference;
  typedef typename BuffType::difference_type difference_type;


  CMyItr( BuffType *pB, size_type pos):
    PtrItr_(pB), PtrPos_(pos){
  };



  friend class CMyItr< const T, const elem_type>;

  elem_type &operator*(){
    return (*PtrItr_)[PtrPos_];
  };

  elem_type *operator->(){
    return &(operator*());
  };

  self_type & operator++(){
    ++PtrPos_;
    return *this;
  };

  self_type operator++(int){
    self_type tmp(*this);
    ++(*this);
    return tmp;
  };

  self_type operator+(difference_type n) {
    self_type tmp(*this);
    tmp.PtrPos_ = tmp.PtrPos_ + n;
    return tmp;
  };

  self_type &operator+=(difference_type n){
    PtrPos_ = PtrPos_ + n;
    return *this;
  };


  self_type & operator--(){
    --PtrPos_;
    return *this;
  };
  /*!
    The decrement operator which decrements the position index.
  */
  self_type operator--(int){
    self_type tmp(*this);
    --(*this);
    return tmp;
  };

  self_type operator-(difference_type n) {
    self_type tmp(*this);
    tmp.PtrPos_ =  tmp.PtrPos_ - n;
    return tmp;
  };

  self_type &operator-=(difference_type n){
    PtrPos_ -= n;
    return *this;
  };

  bool operator!=(const self_type &other) const {
    return PtrPos_ != other.PtrPos_ && PtrItr_ == other.PtrItr_;
  };

  bool operator==(const self_type &other) const {
    return PtrPos_ == other.PtrPos_ && PtrItr_ == other.PtrItr_;
  };

private:
  BuffType * PtrItr_;
  size_type PtrPos_;
};


//----------------------------------------------------------------------//
//----------------------------------------------------------------------//
template < typename T > class CMyBuff {

public:
  enum {default_size = 4 };

  typedef CMyBuff<T> self_type;
  typedef T value开发者_如何学C_type;
  typedef T & reference;
  typedef const T & const_reference;
  typedef T * pointer;
  typedef const T * const_pointer;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef CMyItr<self_type> iterator;
  typedef CMyItr<const self_type> const_iterator;
  typedef std::reverse_iterator<iterator> reverse_iterator;
  typedef std::reverse_iterator<const iterator> const_reverse_iterator;

  /*! Starting for forward iterator.*/
  iterator begin(){
    return iterator(this, 0);
  };
  /*! Forward iterator should go till here.*/
  iterator end(){
    return iterator(this, Size_);
  };

  /*! Starting for constant forward iterator.*/
  const_iterator begin() const {
    return const_iterator(this, 0);
  };
  /*! Constant forward iterator should go till here.*/
  const_iterator end() const {
    return const_iterator(this, Size_);
  };

  /*! Reverse iterator starts from here.*/
  reverse_iterator rbegin(){
    return reverse_iterator(end());
  }
  /*! Reverse iterator end.*/
  reverse_iterator rend() {
    return reverse_iterator(begin());
  }

  /*! Constant reverse iterator starting point.*/
  const_reverse_iterator rbegin() const {
    return const_reverse_iterator(end());
  }
  /*! Constant reverse iterator should end here.*/
  const_reverse_iterator rend() const {
    return const_reverse_iterator( begin());
  }

  /* Ctor for my buffer*/
  explicit CMyBuff(size_type capacity = default_size): 
    Ptr_(NULL),
    Size_(capacity) {
    Ptr_ = new value_type [sizeof(value_type) * Size_];
    Ptr_[0] = 0;
    Ptr_[1] = 1;
    Ptr_[2] = 8;
    Ptr_[3] = 27;
  };


  ~CMyBuff() {
    delete [] Ptr_;
  }


  reference operator[](size_type i){
    return rAtUnChecked(i);
  };

  const_reference operator[](size_type i) const {
    return rAtUnChecked(i);
  };

  size_type size() const {
    return Size_;
  };


  reference rAtUnChecked(size_type k) const {
    return Ptr_[k];
  };

private:
  pointer Ptr_;
  size_type Size_;
};


//------------------------------------------------------------------//
//-----------------------------------------  MAIN ------------------//
// Use the following command line to compile:
// g++-4.4 -ansi -Wall  -std=c++0x mybuffer.cpp -o mybuffer
int main(){

  CMyBuff<double> Buffer;
  CMyBuff < double >::reverse_iterator RItr = Buffer.rbegin();

  //prints last but one element
  std::cout << *(++RItr) << std::endl;

  // The following doesn't compile on g++. Get const related error 
  // containing "discards qualifier"
  //std::cout << *(RItr + 1) << std::endl;

  return 0;
}
//-------------------------------------------------------------------------------//

//-------------------------------------------- code END ----------------//


Your iterator's operator- doesn't mutate state so it should be const.


This may not be an answer, but can you try following:

  1. change, difference_type n to const difference_type &n
  2. Declare operator +() and operator -() as const (as they don't affect this) See if it helps.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜