我正在用c++实现一个数组(出于各种原因,其中之一是了解自定义迭代器)。
在测试时,我注意到它不能在g++ 4.4中编译,但在Visual Studio 2010中运行良好。
我在下面包含了一个示例程序。在这里,我输出了一个玩具数组的最后一个值,这个玩具数组是我使用模板和附带的迭代器类实现的。我得到的编译器错误如下:
$ 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
如果我做*(RItr+1)操作,错误发生,而不是如果我做*(++ RItr)操作。在visualstudio 2010中,无论哪种情况,它都可以工作。
在g++ 2.95中也得到相同的编译错误。没有在Visual Studio 6中尝试过。
有人能解释一下我做错了什么以及如何解决它吗?
谢谢。PS:使用g++ 4.6完全是另一个问题,但那是以后的事了。
//-------------------------------------------- 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_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;
}
//-------------------------------------------------------------------------------//
//-------------------------------------------- 代码结束 ----------------//
你的迭代器的operator-
不会改变状态,所以它应该是const。
这可能不是一个答案,但你可以试着这样做:
- change,
difference_type n
toconst difference_type &n
- 将
operator +()
和operator -()
声明为const
(因为它们不影响this
)看看是否有帮助。