Re: A non std::vector<> definition
I thought of your answer and read the section too and changed the code to:
Code:
#include <std_lib_facilities_4.h>
using namespace std;
template<class T> class rg_ch_vector {
public:
class Iterator;
rg_ch_vector<T>() = default; // Default construtor
rg_ch_vector<T>(initializer_list<T> N) { // Constructor with initializers
for (const auto& l : N)
push_back(l);
}
rg_ch_vector& operator=(const rg_ch_vector& N) { // Copy assignment operator
vec = N.vec;
return *this;
}
rg_ch_vector(const rg_ch_vector& N) { // Copy constructor (deep copy)
vec = N.vec;
}
size_t size() const { return vec.size(); }
Iterator begin() const { return Iterator(vec.begin()); }
// iterator to the first element
Iterator end() const { return Iterator(vec.end()); }
// iterator to one beyond the last element
void push_back(const T& v) { vec.push_back(v); } // insert v at end
T& operator[] (std::size_t pos) { return vec[pos]; }
const T& operator[] (std::size_t pos) const { return vec[pos]; }
protected:
vector<T> vec;
};
//****************************************
template<class T>
class rg_ch_vector<T>::Iterator {
private:
T* iter = nullptr;
friend class rg_ch_vector<T>;
public:
Iterator(T* p) : iter(p) { }
Iterator& operator++() { iter++; return *this; } // forward
Iterator& operator--() { iter--; return *this; } // backward
T& operator*() { return *iter; } // get value (dereference)
bool operator==(const Iterator& b) const { return vec == b.vec; }
bool operator!=(const Iterator& b) const { return vec != b.vec; }
};
//****************************************************************************
int main()
{
rg_ch_vector<int> v1;
v1.push_back(3);
v1.push_back(5);
auto p = v1.begin();
++p;
cout << *p << endl;
system("pause");
return 0;
}
I get an error in line 27 (Iterator begin()) about a non-match conversion.
Look please, when I declare auto p = v1.begin(); in main(), it goes to Iterator begin() const { return Iterator(vec.begin()); } in rg_ch_vector class sending a pointer type T* to Iterator(T* p) : iter(p) { } in the Iterator class.
There, it puts that pointer to iter which is again in type T*.
So in theory nothing looks clearly wrong, but in essence I get that error!
I don't know how to solve that.
Re: A non std::vector<> definition
Code:
Iterator begin() const { return Iterator(vec.begin()); }
vec.begin() returns a type of vector::iterator which you are then trying to create a temp instance of Iterator from - but Iterator doesn't have a constructor that takes a type of vector::iterator. As the Iterator constructor requires a pointer to a type, consider
Code:
Iterator begin() const {return (T*)vec.data();}
There is also a similar issue with end().
Re: A non std::vector<> definition
What does Iterator(vec.begin() in { return Iterator(vec.begin()); } mean please?
1- Iterator is a (user-defined) type, so doesn't that expression try to convert the type of vector::iterator into the type of an Iterator?
2- Or it tries to call a constructor of the class Iterator with the syntax of
Code:
Iterator(vector::iterator p) : iter(p) { }
?
3- And if 2, would it work? That is, could we assign a vector::iterator type, p, to a T* type iter in the Iterator class?
Re: A non std::vector<> definition
Quote:
What does Iterator(vec.begin()) in { return Iterator(vec.begin()); } mean please?
It creates a temp object of class Iterator calling the Iterator class constructor with vec.begin() as the argument. As class Iterator doesn't have a constructor that takes class vector::iterator as an argument, there is a compile error. The class Iterator has only one constructor which takes as argument a type T* (ie a pointer to a type). So the argument used with Iterator( has to be of this type.
So 2) Yes. 3) No. That is why you get the compile error as there is no constructor that takes an argument of vector::iterator for the class Iterator.
Re: A non std::vector<> definition
These are begin and end member functions:
Code:
Iterator begin() const { return (T*)(vec.data()); }
Iterator end() const { return (T*)(vec.data()+vec.size()-1);}
Here what is returned is of type vec.data() (a pointer to the first element) which is then converted to a T*. How do I know that conversion will be possible?
And the return type should be of type Iterator, why no error while a T* is not an Iterator?
I defined:
Code:
bool operator==(const Iterator& b) const { return b == *this; }
bool operator!=(const Iterator& b) const { return b != *this; }
and in main():
Code:
rg_ch_vector<int> v1;
v1.push_back(3);
v1.push_back(5);
rg_ch_vector<int> v2 = { 10, 12, 15, 18 };
auto p1 = v1.begin();
auto p2 = v2.begin();
if (p1 == p2) cout << "Equal\n";
My assumption is: in (p1 ==p2), a pointer to p1 will be sent to the operator== as this and *this is that p1.
p2 is sent to b and therefore return b == *this; should work. But I get an error on that operator:
Severity Code Description Project File Line Suppression State
Warning C4717 'rg_ch_vector<int>::Iterator::operator==': recursive on all control paths, function will cause runtime stack overflow
Re: A non std::vector<> definition
Quote:
And the return type should be of type Iterator, why no error while a T* is not an Iterator?
Because it creates a temp object of class Iterator with constructor T*.
Code:
bool operator==(const Iterator& b) const { return b == *this; }
*this is of type Iterator, so you are trying
Code:
b.operator==(*this);
which calls Iterator operator==(const Iterator* b) which then calls Iterator operator==(const Iterator* b) and so on for ever!
When coding an operator, the code mustn't call itself!
Re: A non std::vector<> definition
I got your point and modified it to this:
Code:
bool operator==(const Iterator& b) const { return iter == b.iter; }
Thanks for guiding me by comments (mostly) and direct me to change the code to what that is right.
One question:
Would this code be the one you'd write if you were offered that exercise? That is, do you accept the code written this way until now and I want to develop it to meet the features of a random-access iterator?
Re: A non std::vector<> definition
Quote:
Would this code be the one you'd write if you were offered that exercise?
No, but knowing extra info about c++ that you'll gain. I'd be deriving a new class from the STL class iterator. See http://www.cplusplus.com/reference/iterator/iterator/
Re: A non std::vector<> definition
Quote:
No, but knowing extra info about c++ that you'll gain. I'd be deriving a new class from the STL class iterator
Thanks. But I probably should have asked the question this way: "... if you were offered this exercise and would use the stuff covered only in the previous chapters of the book?"
It's right that your version differs from mine because I'm in an almost intermediate level of C++ while you're an expert so you'd use more advanced tools for a given task.
I suppose considering the stuff covered in this point of the book (and it's the only book I've read and am reading still on C++) , and also the context of the exercise 18, what is written up to now is probably acceptable, if you don't disagree.
Here is the code for now (still incomplete though):
Code:
#include <std_lib_facilities_4.h>
using namespace std;
template<class T> class rg_ch_vector {
public:
class Iterator;
rg_ch_vector<T>() = default; // Default construtor
rg_ch_vector<T>(initializer_list<T> N) { // Constructor with initializers
for (const auto& l : N)
push_back(l);
}
rg_ch_vector& operator=(const rg_ch_vector& N) { // Copy assignment operator
vec = N.vec;
return *this;
}
rg_ch_vector(const rg_ch_vector& N) { // Copy constructor (deep copy)
vec = N.vec;
}
size_t size() const { return vec.size(); }
Iterator begin() const { return (T*)(vec.data()); }
// iterator to the first element
Iterator end() const { return (T*)(vec.data()+vec.size());}
// iterator to one beyond the last element
void push_back(const T& v) { vec.push_back(v); } // insert v at end
T& operator[] (std::size_t pos) { return vec[pos]; }
const T& operator[] (std::size_t pos) const { return vec[pos]; }
protected:
vector<T> vec;
};
//****************************************
template<class T>
class rg_ch_vector<T>::Iterator {
private:
T* iter = nullptr;
//friend class rg_ch_vector<T>;
public:
Iterator() = default; // Default construtor
Iterator(T* p) : iter(p) { }
Iterator(const Iterator& N) : iter(N.iter) { } // Copy constructor
Iterator& operator=(const Iterator& N) { iter = N.iter; return *this; }
// Copy assignment operator
Iterator& operator++() { iter++; return *this; } // forward prefix
Iterator& operator--() { iter--; return *this; } // backward prefix
Iterator operator++(T) { Iterator temp(*this); ++*this; return temp; }
// forward postfix
Iterator operator--(T) { Iterator temp(*this); --*this; return temp; }
// backward postfix
Iterator operator+(int i) { iter += i; return *this; } //arithmetic operator +
Iterator operator-(int i) { iter -= i; return *this; } //arithmetic operator -
Iterator operator+=(int i) { iter += i; return *this; } //arithmetic operator +=
Iterator operator-=(int i) { iter -= i; return *this; } //arithmetic operator -=
T& operator*() { return *iter; } // get value (dereference)
T* operator&() { return iter; }
bool operator==(const Iterator& b) const { return iter == b.iter; }
bool operator!=(const Iterator& b) const { return iter != b.iter; }
};
What do you think of it?
A couple of questions:
1- We use delete for an object if it's created using a dynamically allocation from the memory via the operator new. So here we don't have any new, hence don't need any delete either. right?
2- I've defined a couple of constructors for both classes! It looks rather redundant although I'm not sure!
3- In the copy assignment operator:
Code:
Iterator& operator=(const Iterator& N) { iter = N.iter; return *this; }
It works but if I define it this way it shows errors:
Code:
Iterator& operator=(const Iterator& N) : iter(N.iter) {return *this; }
I don't see any logical reason for that difference!
Re: A non std::vector<> definition
3. Only a constructor can have a base/member initializer list. As operator=() isn't a constructor, it can't.
Code:
Iterator& operator++() { iter++; return *this; } // forward prefix
Why not
Code:
Iterator& operator++() { ++iter; return *this; } // forward prefix
Code:
Iterator operator++(T) { Iterator temp(*this); ++*this; return temp; }
Why not
Code:
Iterator operator++(T) { Iterator temp(*this); ++iter; return temp; }
Code:
Iterator operator+(int i) { iter += i; return *this; } //arithmetic operator +
Not really. This is operator+=. Operator+ doesn't change this. Hint. Operator+() is often implemented using operator+=().