A non std::vector<> definition
Hi,
Please take a look at exercise 16 here.
I wrote the code below:
Code:
#include <std_lib_facilities_4.h>
using namespace std;
template <class T> class ovector
{
public:
ovector() = default; // default constructor
ovector(const ovector& N) // Copy constructor
{
for (const auto& v : N.vec)
push_back(new T(*v));
}
ovector& operator= (const ovector& N) // Copy assignment
{
auto l = N;
swap(l.vec, vec);
return *this;
}
~ovector() {
for (auto ptr : vec)
delete ptr;
}
auto begin() const { return vec.begin(); }
auto end() const { return vec.end(); }
auto size() const { return vec.size(); }
void push_back(T* ptr) { vec.push_back(ptr); }
void pop_back() { delete vec.back(); vec.pop_back(); }
void resize(size_t n) { vec.resize(n); }
T& operator*(size_t pos) { return *vec[pos]; }
T& operator[] (size_t pos) { return *vec[pos]; }
const T& operator[] (size_t pos) const { return *vec[pos]; }
private:
vector<T*> vec; // vector of pointers
};
//***************************************
int main() {
ovector<double> v1;
for (size_t i = 0; i < 10; i++)
v1.push_back(new double(2.5*i));
cout << "vector<double> v1 = ";
for (const auto& v : v1)
cout << *v << ' ';
cout << endl;
*v1(0) = 3;
system("pause");
return 0;
}
I get these errors on line 54 where I want to use the overloaded operator* there:
Severity Code Description Project File Line Suppression State
Error (active) E0980 call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
Severity Code Description Project File Line Suppression State
Error C2064 term does not evaluate to a function taking 1 arguments
What the problem could be please?
Re: A non std::vector<> definition
Code:
T& operator*(size_t pos) { return *vec[pos]; }
From this definition of operator*, it is used like this
why?? - which is probably not what you were expecting/wanting.
Re: A non std::vector<> definition
Quote:
why?? - which is probably not what you were expecting/wanting.
I haven't ever seen any use like : v1 * 0 = 3;. It looks very awkward. So I think the exercise wants some other declaration of the operator*.
And do you think this code is good as an answer to the exercise?
Re: A non std::vector<> definition
You're defined operator* as a binary operator - not as a unary operator that is required when it is used for pointer dereference. For a binary operator you have to provide 2 arguments. When defined as a member function, the first argument is of a class type (eg v1) and the second argument is what is defined for operator*(). In this case a type of size_t. So the syntax to use is eg v1 * 2. What the operator * actually does is decided by the operator() code. It is good practice that what the operator does seems reasonable in the context of someone reading the code - which is why in this case the way it is used does look very awkward. It does work as coded, but is not intuitive as to its meaning when reading code. if I saw v1 * 2 in code and knew that v1 was a vector I would assume that this statement multiplied every element of the vector by 2 - not provide a reference to the second element.
Re: A non std::vector<> definition
Quote:
Please take a look at exercise 16 here.
Quote:
15. Define a pvector to be like a vector of pointers except that it contains pointers to objects and its destructor deletes each object.
16. Define an ovector that is like pvector except that the [] and * operators return a reference to the object pointed to by an element rather than the pointer.
How have you implemented the pvector - and the * operator for it? * is not a normal operator (as a pointer deference) for a vector. If the vector held pointers then * would be used to deference a pointer but * would then be an operator for the underlying vector type - not of the vector itself.
Re: A non std::vector<> definition
As far as I understood the case for the operator *, we should firstly have something that that operator is defined (overloaded) for, second, some number as an index to refer to the element (pointer) in the ovector, therefore it sounds that we need a binary operator to characterise these two specification. This is my thought. If you think other way, how would you please defined that operator?
Quote:
2. What the operator * actually does is decided by the operator() code.
Do you mean the default operator()? (If any)
Apart from above, I also thought of defining an operator() to be used in main() and it itself calls the operator* for getting the value. No success yet.
Quote:
If the vector held pointers then * would be used to deference a pointer but * would then be an operator for the underlying vector type - not of the vector itself.
I couldn't understand this completely, but here is code for exercise 15:
Code:
#include <std_lib_facilities_4.h>
using namespace std;
template <class T> class pvector
{
public:
pvector() = default; // default constructor
pvector(const pvector& N) // Copy constructor
{
for (const auto& v : N.vec)
push_back(new T(*v));
}
pvector& operator= (const pvector& N) // Copy assignment
{
auto l = N;
swap(l.vec, vec);
return *this;
}
~pvector() {
for (auto ptr : vec)
delete ptr;
}
auto begin() const { return vec.begin(); }
auto end() const { return vec.end(); }
auto size() const { return vec.size(); }
void push_back(T* ptr) { vec.push_back(ptr); }
void pop_back() { delete vec.back(); vec.pop_back(); }
void resize(size_t n) { vec.resize(n); }
T*& operator[] (std::size_t pos) { return vec[pos]; }
const T*& operator[] (std::size_t pos) const { return vec[pos]; }
private:
vector<T*> vec; // vector of pointers
};
Re: A non std::vector<> definition
Quote:
2. What the operator * actually does is decided by the operator() code.
Do you mean the default operator()? (If any)
Sorry, my bad. I meant the code for operator*()
Quote:
As far as I understood the case for the operator *, we should firstly have something that that operator is defined (overloaded) for, second, some number as an index to refer to the element (pointer) in the ovector, therefore it sounds that we need a binary operator to characterise these two specification. This is my thought. If you think other way, how would you please defined that operator?
For operator*() on a vector I don't see different - but I wouldn't define operator*() for a vector at all - except as for scalar/vector multiplication. Any other guru got any idea as to what Stroustrup is referring?
Re: A non std::vector<> definition
Thank you very much.
For the exercise 17 on the screenshot of the first post, I again can't understand it well enough. :(
We can't give arguments to the destructor to tell it what object it deletes. I try to code it myself but would you please explain the exercise what is its meaning?
Re: A non std::vector<> definition
Quote:
Originally Posted by
tomy12
Thank you very much.
For the exercise 17 on the screenshot of the first post, I again can't understand it well enough. :(
We can't give arguments to the destructor to tell it what object it deletes. I try to code it myself but would you please explain the exercise what is its meaning?
Quote:
17. Define an ownership_vector that holds pointers to objects like pvector, but provides a mechanism for the user to decide which objects are owned by the vector (ie which objects are deleted by the destructor). Hint: This exercise is simple if you were awake for chapter 13.
So were you awake for Chapter 13? See 13.10 and Appendix E.4 for the hints!
Re: A non std::vector<> definition
Done! thanks.
Does the exercise 18 mean that we should define an iterator (class) for the std::vector<>? But the vector itself has its own begin() and end() for range checking!
And what does "a random access iterator" mean please?
The problem is only understanding the question the way it is meant. Then I myself will write the code.
Re: A non std::vector<> definition
See http://www.cplusplus.com/reference/iterator/ for info re the various types of iterator.
I think it means an iterator that can't go out of range. Consider
Code:
vector<int> vi {1,1,1,1,1}
for (auto i = vi.begin(); *i || !*i; ++i);
the iterator i will go out of range as the loop terminator is based upon the value pointed to by the iterator and in this example the termrination condition is always true so i is continually incremented. The 'correct code' is
Code:
vector<int> vi {1,1,1,1,1}
for (auto i = vi.begin(); i != vi.end() && *i || !*i; ++i);
but the exercise seems to want an iterator that is range checked (can't go out of bounds of the container either below or above).
Re: A non std::vector<> definition
Thank you.
I've started using this code as a base and will gradually add other features to meet the requirements of a random-access iterator:
Is this base correct up to now?
Code:
#include <std_lib_facilities_4.h>
using namespace std;
template<class T> class rg_ch_vector {
public:
rg_ch_vector() = default; // Default constructor
rg_ch_vector(initializer_list<T> N) { // Constructor with initializers
for (const auto& l : N)
vec.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;
}
~rg_ch_vector() { // Destructor
~vec();
}
size_t size() const { return vec.size(); }
auto begin() const { return vec.begin(); }
auto end() const { return vec.end(); }
void push_back(const T& v) { vec.push_back(v); }
void push_front(const T& v) { vec.push_front(v); }
void pop_front() { vec.pop_front(); }
void pop_back() { vec.pop_back(); }
T& front() const { return vec.front(); }
T& back() const { return vec.back(); }
void operator++() { ++vec; } // forward
void operator--() { --vec; } // backward
T& operator*() { return *vec; } // get value (dereference)
bool operator==(const rg_ch_vector& b) const { return vec == b.vec; }
bool operator!=(const rg_ch_vector& b) const { return vec != b.vec; }
ostream& operator<<(const T& b) { return b; }
private:
vector<T> vec;
};
//********************************************
int main()
{
rg_ch_vector<double> vd;
vd.push_back(3.5);
vd.push_back(8);
vd.push_back(7.3);
vd.push_back(16);
cout << *vd << ' ';
++vd;
cout << *vd << '\n';
system("pause");
return 0;
}
I get the error illegal indirection in the line 43 (T& operator*()). why please?
And I think the destructor doesn't work as needed either. Any idea about the reason?
And since we haven't any dynamically allocated memory (using new) so there seems to be no need for having a destructor, I suppose.
Re: A non std::vector<> definition
Quote:
I get the error illegal indirection in the line 43 (T& operator*()). why please?
vec is of type class vector for which you can't use operator*() to deference. You need to specify an element in the vector to dereference.
Code:
void operator++() { ++vec; } // forward
void operator--() { --vec; } // backward
This isn't right either for the same reason. The iterator should be incremented/decremented not the vector itself.
Quote:
there seems to be no need for having a destructor
Correct with the code as shown as vector has its own destructor which will get called.
Re: A non std::vector<> definition
1- I thought since the exercise has specified that we are to define an iterator (a random-access iterator), we must have an iterator. So I went for changing the code this way. I'm still not completely sure if it's exactly what the exercise wants or not. But I also think the issue is simpler than what I've thought of. I defined a class named Iterator. If possible please take a look at this whether it's as a whole right for the exercise up to now.
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 vec.being(); } // iterator to the first element
Iterator end() const { return 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]; }
};
//****************************************
template<class T>
class rg_ch_vector<T>::Iterator {
private:
vector<T>* vec;
friend class rg_ch_vector<T>;
public:
Iterator(vector<T>* p) : vec(p) { }
Iterator& operator++() { Iterator p = vec + 1; return p; } // forward
Iterator& operator--() { Iterator p = vec - 1; return p; } // backward
T& operator*() { return vec*; } // 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> v;
v.push_back(3);
v.push_back(5);
cout << v[0] << endl;
auto p = v.begin();
++p;
cout << *p << endl;
system("pause");
return 0;
}
2- I get the error below for T& operator*() { return vec*; } // get value (dereference).
error: syntax error: ';'
I think by an element, you meant I should declare a variable type T to be populated by what the member functions of class rg_ch_vector return, so that its value can be used in Iterator class functions like T& operator*(). Incorrect?
Re: A non std::vector<> definition
Quote:
But I also think the issue is simpler than what I've thought of. I defined a class named Iterator.
Yes, Recap section 20.4.2
Code:
Iterator begin() const { return vec.being(); } // iterator to the first element
Iterator end() const { return vec.end(); } // iterator to one beyond the last element
Nice, but no. vec.begin() returns type vector::iterator which is not the same as your Iterator class. You need to return your type Iterator.