I have a problem with a const iterator because I try to iterate an array of
pointers but when I try to print it, it returns the array that the first
pointer points at. How can I fix it?
The first array is an array of T and the second array is an array of pointers
to the first array:
class const_iterator {
public:
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
const_iterator() : ptr(0) { }
const_iterator(const const_iterator &other) : ptr(other.ptr) { }
const_iterator& operator=(const const_iterator &other) {
ptr = other.ptr;
return *this;
}
~const_iterator() { }
reference operator*() const {
return *ptr;
}
pointer operator->() const {
return ptr;
}
const_iterator operator++(int) {
const_iterator tmp(ptr);
++ptr;
return tmp;
}
const_iterator& operator++() {
++ptr;
return *this;
}
bool operator==(const const_iterator &other) const {
return other.ptr==ptr;
}
bool operator!=(const const_iterator &other) const {
return other.ptr!=ptr;
}
private:
const T *ptr;
friend class SortedArray;
const_iterator(const T*p) : ptr(p){ }
};
const_iterator begin() const {
return const_iterator(*Array);
}
const_iterator end() const {
return const_iterator(*Array+index);
}
Related
i have to implement a forward iterator on a stack based on arrays. I can't use std::vectors or anything, i just need that. My development of this program stopped when i begun with forward iterator, and in particular with the operators.
I have a method that takes a generic sequence, and from that, given an offset, creates a stack:
template <typename IterT>
stack(IterT begin, IterT end) : _stack(0), _size(0), _capacity(0) {
try {
for(; begin!=end; ++begin) {
push(static_cast<T>(*begin));
}
}
catch(...) {
clear(); //my method to destroy the stack
throw;
}
}
In my main i do the following:
int a[5] = {1, 2, 3, 4, 5};
stack<int> sint(a, a+5);
cout << sint << endl;
But when the code runs the stack is created but not printed. Can somebody help me? And also give me other helps(on code indentation, improvements, etc...) Thank you, I will post the iterator code forward.
class const_iterator {
const T* data;
unsigned int index;
public:
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
const_iterator() : data(0){}
const_iterator(const T* arr) : data(arr) {}
const_iterator(const const_iterator &other)
: data(other.data){ }
const_iterator& operator=(const const_iterator &other) {
data = other.data;
return *this;
}
~const_iterator() {
data = 0;
}
reference operator*() const {
return *data;
}
pointer operator->() const {
return &(data);
}
const_iterator operator++(int) {
const_iterator tmp(*this);
++*this;
return tmp;
}
const_iterator& operator++() {
++data;
return *this;
}
bool operator==(const const_iterator &other) const {
return data[index] == other.data[index];
}
bool operator!=(const const_iterator &other) const {
return data[index] != other.data[index] ;
}
private:
friend class stack;
const_iterator(unsigned int ind) :
index(ind){}
}; // class const_iterator
const_iterator begin() const {
cout << "begin" << _stack[_size-1] << endl;
return const_iterator(_stack[_size-1]);
}
const_iterator end() const {
cout << "end" << _stack[0] << endl;
return const_iterator(_stack[0]);
}
Last but not least i redefined the << operator to fit the iterator:
template <typename T>
std::ostream &operator<<(std::ostream &os, const stack<T> &st) {
typename stack<T>::const_iterator i, ie;
for(i = st.begin(), ie = st.end(); i!=ie; ++i){
os << *i << std::endl;
}
return os;
}
The code for the stack is the following (I omitted something for readability).
stack()
: _capacity(0), _size(0), _stack(0){}
void push (const T &value){
if (_size == _capacity){ //raddoppio la dimensione
if(_capacity == 0)
++_capacity;
_capacity *= 2;
T* tmp = new T[_capacity];
copy_n(_stack, _size, tmp);
swap(_stack, tmp);
delete[] tmp;
}
_stack[_size] = value;
++_size;
}
void pop(){
T _tmp;
if(!is_empty()){
_tmp = _stack[_size-1];
--_size;
}
}
If you want to create an iterator that looks like a pointer, you don't need index, because data plays its role. Comparison operator should compare datas, not values:
bool operator==(const const_iterator &other) const {
return data == other.data;
}
If you want to create a reverse iterator, it is slightly more complex. First, operator++ should decrement data. Second, dereference operator should return not *data, but *(data - 1). Third, data in the begin() iterator should point to stack[size], and data in the end() iterator should point to stack[0]. You don't need a destructor in any case.
I followed the previous advices and here's the edited result, still i can't figure out how to properly use the constructor in the private section
class const_iterator {
const T *data;
public:
/* ITERATOR TRAITS HERE */
const_iterator() : data(0){}
const_iterator(const T* arr) : data(arr) {}
const_iterator(const const_iterator &other)
: data(other.data){ }
const_iterator& operator=(const const_iterator &other) {
data = other.data;
return *this;
}
~const_iterator() {
data = 0;
}
reference operator*() const {
return *data;
}
pointer operator->() const {
return &(data);
}
const_iterator operator++(int) {
const_iterator tmp(*this);
++*this;
return tmp;
}
const_iterator& operator++() {
++data;
return *this;
}
bool operator==(const const_iterator &other) const {
return data == other.data;
}
bool operator!=(const const_iterator &other) const {
return data != other.data;
}
private:
friend class stack;
const_iterator(const T *d) {
data = d;
}
}; // classe const_iterator
const_iterator begin() const {
return const_iterator(_stack[_size-1]);
}
const_iterator end() const {
return const_iterator(_stack[0]);
}
I wrote this Vector class and one nested Iterator class and one const_Iterator class, now I have to secure my Vector so my Iterator doesn't point beyond .end() with for instance my operator ++ method and to throw an exception if i try.
so in my iterator class I cannot access .end() because its a vector method. so I was thinking, instead of pointing on values in my Iterator class I point on the whole vector but i cannot access .end() with a Vector* .
Am I on the right way to the solution and if I am how can I pass my Vector so I can use it in the way I intend to?
class Vector{
public:
using value_type= double;
using size_type= size_t;
using difference_type= ptrdiff_t;
using reference = double&;
using const_reference= const double&;
using pointer = double*;
using const_pointer= const double*;
using iterator = double*;
using const_iterator= const double*;
private:
size_t sz;
size_t max_sz;
double* values=nullptr;
class const_Iterator{
public:
using value_type = double;
using difference_type = ptrdiff_t;
using reference = double&;
using pointer = double*;
using iterator_category = std::forward_iterator_tag;
private:
double* ptr;
size_t cnt;
public:
const_Iterator(double* p){
ptr=p;
cnt=0;
}
const_Iterator& operator++ () {
ptr++;
cnt = 0;
return *this;
}
bool operator==(const const_Iterator& rop)const {
return this->ptr == rop.ptr;
}
bool operator!=(const const_Iterator& rop)const {
return this->ptr != rop.ptr;
}
const double operator* () const {
return *ptr;
}
friend Vector::difference_type operator-(const Vector::const_Iterator& lop,const Vector::const_Iterator& rop) {
return lop.ptr-rop.ptr;
}
};
class Iterator{
public:
using value_type = double;
using difference_type = ptrdiff_t;
using reference = double&;
using pointer = double*;
using iterator_category = std::forward_iterator_tag;
private:
double* ptr;
size_t cnt;
public:
Iterator(double* p){
ptr=p;
cnt=0;
}
Iterator& operator++() {
ptr++;
cnt = 0;
return *this;
}
Iterator operator++(int){
Iterator a(ptr);
ptr++;
return a;
}
bool operator==( Iterator& rop) {
return this->ptr != rop.ptr;
}
bool operator!=(const Iterator& rop) {
return this->ptr != rop.ptr;
}
double& operator*() {
return *ptr;
}
operator const_Iterator() const{
return const_Iterator(ptr);
};
};
const_Iterator end() const{return const_Iterator(values+sz);}
const_Iterator begin() const{return const_Iterator(values);}
Iterator begin() { return values; }
Iterator end() { return values + sz; }
size_t min_sz = 5;
Vector();
Vector(size_t);
Vector(const Vector&);
Vector (initializer_list<double> );
void push_back(double);
void reserve(size_t);
void pop_back();
bool empty();
void clear();
Vector& operator=(const Vector&);
const double& operator[] (size_t) const;
double& operator[] (size_t) ;
void fit_to_shrink();
size_t size()const {return sz;}
ostream& print(ostream&) const;
};
Your iterator may look like:
class Iterator{
public:
// ... using type
private:
Vector* parent;
std::size_t index;
public:
Iterator(Vector& v, std::size_t index) : ptr(&v), index(index) {}
Iterator& operator++() {
if (index == parent->size()) {
throw std::runtime_error("++ on end iterator");
}
++index;
return *this;
}
Iterator operator++(int){
Iterator old(*this);
++(*this);
return old;
}
bool operator==(const Iterator& rhs) const {
if (parent != rhs.parent) {
throw std::runtime_error("You compare iterator of different containers");
}
return index == rhs.index;
}
bool operator!=(const Iterator& rop) const { return !(*this == rhs); }
double& operator*() { return parent->at(index); } // `at` throws on invalid index
// ...
};
And your vector:
Iterator Vector::begin() { return Iterator(this, 0);}
Iterator Vector::end() { return Iterator(this, size());}
I'm trying to make the iterator work properly, and for the inequality i != a.end().
I get the error
no know conversion from argument 2 from 'const a3::vector<int>::iterator' to 'const a3::vector<int>&
for the friend function. I need the function to check if the iterator is not equal to vector.end() and am unsure how I would do it.
Class
#include <iostream>
using std::cout;
using std::endl;
namespace a3
{
template <typename T>
class vector
{
public:
class iterator {
public:
int index_;
vector* a_;
iterator() : index_(-1), a_(0) {}
iterator(int index, vector* a) : index_(index), a_(a) {}
iterator& operator=(const iterator& itr)
{
a_ = itr.a_;
index_ = itr.index_;
return *this;
}
iterator& next() {
index_++;
return *this;
}
iterator& operator++() {
return next();
}
int& operator*() { return (*a_)[index_]; }
};
private:
T* mem_;
int sz_;
public:
vector(int sz) : sz_(sz), b_(0, this), e_(sz, this)
{
mem_ = new T[sz];
}
~vector() { delete[] mem_; }
const T& operator[](T i) const { return mem_[i]; }
T& operator[](T i) { return mem_[i]; }
const int& get_size() const { return sz_; }
const iterator& begin() { return b_; }
const iterator& end() { return e_; }
friend bool operator!=(const iterator& itr1, const vector<T>& vec1)
{
return !(itr1.index_ == vec1.end);
}
private:
iterator b_;
iterator e_;
};
}
Main Function
#include "a3_vector.cpp"
int main(int argc, char** argv)
{
using namespace a3;
vector<int> a(10); // allocate an int array of size 10
for (int i=0; i<10; ++i) a[i] = i*2;
// a now looks as follows
//0,2,4,6,8,10,12,14,16,18
// prints the content of the array
vector<int>::iterator i;
for (i = a.begin(); i != a.end(); i.next()) {
cout << *i << endl;
}
}
This is fundamentally wrong:
friend bool operator!=(const iterator& itr1, const vector<T>& vec1)
Iterator comparisons should compare iterators. What you want are comparison operators that look like this:
friend bool operator!=(const iterator& itr1, const iterator& itr2);
friend bool operator==(const iterator& itr1, const iterator& itr2);
After all, that's what this expression is trying to do:
i != a.end()
You're trying to compare two iterators. The error is just trying to convert a.end() to a const vector<T>&, since that's the match that it found for !=. Simply fix != to take an iterator as the second argument and you'll be fine.
I have 2 classes:
class iterator {
Node<K,V>* n;
public:
iterator(){
std::cout<<"new empty iterator"<<std::endl;
};
iterator(const iterator& iter):n(iter.n){
std::cout<<"copy iterator"<<std::endl;
}
explicit iterator(Node<K,V>* nodePtr):n(nodePtr) {
std::cout<<"create iterator with Node Ptr"<<std::endl;
}
iterator& operator=(const iterator& iter);
void operator++();
Node<K,V>& operator*();
bool operator!=(const iterator& iter);
K& operator[](const Key& k)const;
V& operator[](const Val& v)const;
Node<K,V>* getNodePtr()const{
std::cout<<"get Node Ptr"<<std::endl;
return n;
}
friend class Map;
};
class const_iterator :public iterator {
const Node<K,V>* n;
public:
const_iterator(){
std::cout<<"new empty const_iterator"<<std::endl;
};
const_iterator(const iterator& iter):
n(iter.getNodePtr()){
std::cout<<"convert"<<std::endl;
}
const_iterator(const const_iterator& iter):n(iter.n){}
explicit const_iterator(const Node<K,V>* node):n(node){}
const_iterator& operator=(const const_iterator& iter){
n = iter.n;
return *this;
}
const Node<K,V>& operator*(){
return *n;
}
friend class Map;
};
iterator begin()const{
return iterator(firstKey);
}
iterator end()const{
return iterator(dummyKey);
}
I want it to make an automatic conversion between the 2 classes using:
const_iterator(const iterator& iter):
n(iter.getNodePtr()){
std::cout<<"convert"<<std::endl;
}
to do something like this for example:
Map<int,int>::const_iterator it = m.begin();
now, the thing is, that this constructor calls for some reason iterator(); in the first class and I can't figure out why.
I know begin() and end() have some standart versions, but I can't use any of it here. I also can't make Map to be const, or write a conversion function.
any help?
You've made iterator a base class of const_iterator, so an iterator constructor will (and should) be called as part of constructing a const_iterator.
If you will define data storage as
const Map<int, int> data;
instead of
Map<int, int> data;
const version of begin() and end() will be invoked.
Also, C++11 standard containers add cbegin() and cend() for that purpose. You could re-difine it as follows:
const_iterator cbegin()const{
return const_iterator(firstKey);
}
const_iterator cend()const{
return const_iterator(dummyKey);
}
There're cases when a library source is available, and it has to support variable parameters in general, but in practice these parameters are commonly constants.
Then it may be possible to optimize things by special handling of constant parameters (eg. use static arrays instead of heap allocation), but for that its necessary to determine whether something is a constant first (or maybe define some macros, but its less convenient).
So here's a working implementation.
Update: also here: http://codepad.org/ngP7Kt1V
Is it really a valid C++ ?
Is there a way to get rid of these macros? (is_const() can't be a function because the function dependence won't work in array size expression; also it can't be a template because that won't accept a variable parameter either. )
Update: Here's an update with something more like intended usage.
The compiler won't generate any code for the if(N==0) branch if N is not 0.
Same way we can switch to completely different data structures if we want.
Sure its not perfect, but that's why I posted this question.
#include <stdio.h>
struct chkconst {
struct Temp { Temp( int x ) {} };
static char chk2( void* ) { return 0; }
static int chk2( Temp ) { return 0; }
};
#define is_const_0(X) (sizeof(chkconst::chk2(X))<sizeof(int))
#define is_const_0i(X) (sizeof(chkconst::chk2(X))>sizeof(char))
#define is_const(X) is_const_0( (X)^((X)&0x7FFFFFFF) )
#define const_bit(X1,bit) (is_const_0i((X1)&(1<<bit))<<bit)
#define const_nibl(X1,bit) const_bit(X1,bit) | const_bit(X1,(bit+1)) | const_bit(X1,(bit+2)) | const_bit(X1,(bit+3))
#define const_byte(X1,bit) const_nibl(X1,bit) | const_nibl(X1,(bit+4))
#define const_word(X1,bit) const_byte(X1,bit) | const_byte(X1,(bit+8))
#define const_uint(X1) const_word(X1,0) | const_word(X1,16)
#define const_switch_word( X1, X2 ) (is_const(X1) ? const_word(X1,0) : X2)
#define const_switch_uint( X1, X2 ) (is_const(X1) ? const_uint(X1) : X2)
const int X1 = 222;
const int X2 = printf( "" ) + 333;
char Y1[ const_switch_word(X1,256) ];
char Y2[ const_switch_word(X2,256) ];
template< int N >
void test( int N1 ) {
char _buf[N>0?N:1];
char* buf = _buf;
if( N==0 ) {
buf = new char[N1];
}
printf( "%08X %3i %3i\n", buf, N, N1 );
}
#define testwrap(N) test< const_switch_word(N,0) >( N )
int main( void ) {
printf( "%i %i %i\n", X1, is_const(X1), sizeof(Y1) );
printf( "%i %i %i\n", X2, is_const(X2), sizeof(Y2) );
testwrap( X1 );
testwrap( X2 );
}
If you're working with GCC, use __builtin_constant_p to tell you whether something is a compile time constant. The documentation includes examples like
static const int table[] = {
__builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
/* ... */
};
is_const should be more reliable. On gcc-4.4 for example, the following:
int k=0;
printf("%d\n",is_const(k),is_const(k>0));
prints:
0,1
GCC is quite ambitious folding constant expressions which are not integral constant expressions by the words of the standard. A potentially better definition of is_const could be:
#define is_const(B)\
(sizeof(chkconst::chk2(0+!!(B))) != sizeof(chkconst::chk2(0+!(B))))
Aside from that, your technique is awesome, because I can finally write a SUPER_ASSERT macro which is checked during compilation if the assertion expression if compile-time and during runtime otherwise:
#define SUPER_ASSERT(X) {BOOST_STATIC_ASSERT(const_switch_uint(X,1));assert(X);}
I'll look into that const_switch_xxx() thing later. I have no idea how to implement another way, the deconstruct/reconstruct trick is brilliant.
If you can pass in a template parameter then it is guaranteed to be a constexpr (the Standard's term for compile-time expressions). If it's not passed by template parameter, then it's not a constexpr. There is no way around this.
What would be much easier is to hand-roll a stack allocated variable length array class using alloca. This will guarantee stack allocation for arrays, regardless of whether or not they're static or not. In addition, you can get much of the same iteration functionality of a vector/boost::array.
#define MAKE_VLA(type, identifier, size) VLA< (type) > identifier ( alloca( (size) * sizeof ( type ) ), (size) );
template<typename T> class VLA {
int count;
T* memory;
VLA(const VLA& other);
public:
// Types
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef T value_type;
typedef std::size_t size_type;
class iterator {
mutable T* ptr;
iterator(T* newptr)
: ptr(newptr) {}
public:
iterator(const iterator& ref)
: ptr(ref.ptr) {}
operator pointer() { return ptr; }
operator const pointer() const { return ptr; }
reference operator*() { return *ptr; }
const reference operator*() const { return *ptr; }
pointer operator->() { return ptr; }
const pointer operator->() const { return ptr; }
iterator& operator=(const iterator& other) const {
ptr = iterator.ptr;
}
bool operator==(const iterator& other) {
return ptr == other.ptr;
}
bool operator!=(const iterator& other) {
return ptr != other.ptr;
}
iterator& operator++() const {
ptr++;
return *this;
}
iterator operator++(int) const {
iterator retval(ptr);
ptr++;
return retval;
}
iterator& operator--() const {
ptr--;
return *this;
}
iterator operator--(int) const {
iterator retval(ptr);
ptr--;
return retval;
}
iterator operator+(int x) const {
return iterator(&ptr[x]);
}
iterator operator-(int x) const {
return iterator(&ptr[-x]);
}
};
typedef const iterator const_iterator;
class reverse_iterator {
mutable T* ptr;
reverse_iterator(T* newptr)
: ptr(newptr) {}
public:
reverse_iterator(const reverse_iterator& ref)
: ptr(ref.ptr) {}
operator pointer() { return ptr; }
operator const pointer() const { return ptr; }
reference operator*() { return *ptr; }
const reference operator*() const { return *ptr; }
pointer operator->() { return ptr; }
const pointer operator->() const { return ptr; }
reverse_iterator& operator=(const reverse_iterator& other) const {
ptr = reverse_iterator.ptr;
}
bool operator==(const reverse_iterator& other) {
return ptr == other.ptr;
}
bool operator!=(const reverse_iterator& other) {
return ptr != other.ptr;
}
reverse_iterator& operator++() const {
ptr--;
return *this;
}
reverse_iterator operator++(int) const {
reverse_iterator retval(ptr);
ptr--;
return retval;
}
reverse_iterator& operator--() const {
ptr++;
return *this;
}
reverse_iterator operator--(int) const {
reverse_iterator retval(ptr);
ptr++;
return retval;
}
reverse_iterator operator+(int x) const {
return reverse_iterator(&ptr[-x]);
}
reverse_iterator operator-(int x) const {
return reverse_iterator(&ptr[x]);
}
};
typedef const reverse_iterator const_reverse_iterator;
typedef unsigned int difference_type;
// Functions
~VLA() {
for(int i = 0; i < count; i++)
memory[i].~T();
}
VLA(void* stackmemory, int size)
: memory((T*)stackmemory), count(size) {
for(int i = 0; i < count; i++)
new (&memory[i]) T();
}
reference at(size_type pos) {
return (reference)memory[pos];
}
const_reference at(size_type pos) {
return (const reference)memory[pos];
}
reference back() {
return (reference)memory[count - 1];
}
const_reference back() const {
return (const reference)memory[count - 1];
}
iterator begin() {
return iterator(memory);
}
const_iterator begin() const {
return iterator(memory);
}
const_iterator cbegin() const {
return begin();
}
const_iterator cend() const {
return end();
}
const_reverse_iterator crbegin() const {
return rbegin();
}
const_reverse_iterator crend() const {
return rend();
}
pointer data() {
return memory;
}
const_pointer data() const {
return memory;
}
iterator end() {
return iterator(&memory[count]);
}
const_iterator end() const {
return iterator(&memory[count]);
}
reference front() {
return memory[0];
}
const_reference front() const {
return memory[0];
}
reverse_iterator rbegin() {
return reverse_iterator(&memory[count - 1]);
}
const_reverse_iterator rbegin() const {
return const_reverse_iterator(&memory[count - 1]);
}
reverse_iterator rend() {
return reverse_iterator(memory[-1]);
}
const_reverse_iterator rend() const {
return reverse_iterator(memory[-1]);
}
size_type size() {
return count;
}
reference operator[](int index) {
return memory[index];
}
const reference operator[](int index) const {
return memory[index];
}
};
Note that I haven't actually tested this code, but it would be MUCH easier to grab, use, and maintain than to maintain that monstrosity in your OP.