Overloading operator->

N

Nico

I want to create a const_iterator that gives me access to dynamically
generated objects.
For example see the class Polygon that contains a list of points
stored as following doubles in a vector (x1, y1, x2, y2, ...). The
iterator should return only pairs of doubles to avoid possible
confusion of the user of the class Polygon. (The storage format is
needed for conversion to other libraries.)
The code for Polygon below compiles well, but the problem is using the
operator->.

inline pair<double,double> operator->() { return pair<double,
double>(*_points, *(_points+1)); }

If I use the -> operator like this:
Polygon p;
p.addPoint(5.0, 5.0);
for(Polygon::iterator it = polygon.begin(); it != polygon.end(); +
+it) {
cout << it->first << endl;
cout << (it).second << endl;
}

I get the following compile error: result of 'operator->()' yields
non-
pointer result
The second line with the * operator gives no errors.

Is it possible to overload the operator-> in the intended way?

#include <utility>
#include <vector>
using namespace std;
class Polygon{
public:
class iterator;
inline Polygon() : _points() {};
inline Polygon(unsigned size) : _points(size*2) {};
virtual ~Polygon() {};
inline void addPoint(double x, double y) {
_points.push_back(x);
_points.push_back(y);
}
inline Polygon::iterator begin() const
{ return iterator(*this, 0); }
inline Polygon::iterator end() const
{ return Polygon::iterator(*this, _points.size()); }
inline void clear() { _points.clear(); }
inline void resize(unsigned i) { _points.resize(i*2); }
inline unsigned size() const { return _points.size()/2; }
inline const double* data() const { return &_points[0]; }

class iterator : public
std::iterator<std::random_access_iterator_tag, pair<double, double> >
{
private:
const Polygon* _polygon;
unsigned _offset;
vector<double>::const_iterator _points;
public:
inline iterator(const Polygon& p, unsigned offset = 0) :
_polygon(&p), _offset(offset), _points(p._points.begin())
{ }
inline iterator(const iterator& i) :
_polygon(i._polygon), _offset(i._offset),
_points(i._points) { }
inline pair<double, double> operator*() const
{ return pair<double, double>(*_points, *(_points+1)); }
inline pair<double, double> operator[](unsigned i) const
{ return pair<double, double>(*(_points+(i*2)),*(_points+
(i*2)+1)); }

inline pair<double,double> operator->()
{
return pair<double,double>(*_points, *(_points+1));
}

inline iterator& operator++()
{ ++_points; ++_points; ++_offset; return *this; }
inline iterator operator++(int)
{ iterator p = *this; ++(*this); return p; }
inline iterator& operator=(iterator& i) {
if (this == &i) { return *this; }
_polygon = i._polygon;
_offset = i._offset;
_points = i._points;
return *this;
}
inline bool operator==(const iterator& i) const
{return _polygon == i._polygon && _offset == i._offset;}
inline bool operator<(const iterator& i) const
{ return _polygon < i._polygon || (_polygon ==i._polygon &&
_offset < i._offset); }
inline bool operator!=(const iterator& i) const { return !
(*this == i); }
inline bool operator>(const iterator& i) const { return i <
*this; }
inline bool operator<=(const iterator& i) const { return !(i <
*this); }
inline bool operator>=(const iterator& i) const { return !
(*this < i); }
};
private:
vector<double> _points;
};
#endif

P.S: I use g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) on
a 64bit x86 AMD machine.
 
V

Victor Bazarov

Nico said:
I want to create a const_iterator that gives me access to dynamically
generated objects.
[..]

Are you going to post it every few minutes? For how long?

V
 
R

Roland Pibinger

I want to create a const_iterator that gives me access to dynamically
generated objects.
The code for Polygon below compiles well, but the problem is using the
operator->.

inline pair<double,double> operator->() { return pair<double,
double>(*_points, *(_points+1)); }

I get the following compile error: result of 'operator->()' yields
non->pointer result

Define an iterator with a pointer as result type.
class iterator : public
std::iterator<std::random_access_iterator_tag, pair<double, double> >
{
private:

inline pair<double,double> operator->()

// pointer and reference are defined in the base class template
pointer operator>() const;
reference operator*() const;
 
N

Nico

Define an iterator with a pointer as result type.

I can't return a pointer, because I have no pair-object on the heap!
If I would
return new pair<double,double>(*_points, *(_points+1));
I would create a memory leak!
So I want just to return a copy of my generated pair that will be
deleted when out of scope of the calling function.
I am guessing you meant
pointer operator->() const;

Of course. But that's not the point.
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

I can't return a pointer, because I have no pair-object on the heap!
If I would
return new pair<double,double>(*_points, *(_points+1));
I would create a memory leak!
So I want just to return a copy of my generated pair that will be
deleted when out of scope of the calling function.

I think returning a smart pointer would work.
 
K

Kai-Uwe Bux

Nico said:
I can't return a pointer, because I have no pair-object on the heap!
If I would
return new pair<double,double>(*_points, *(_points+1));
I would create a memory leak!
So I want just to return a copy of my generated pair that will be
deleted when out of scope of the calling function.
[snip]

Is there a reason why you have a data member

std::vector<double>

where x-coordinates and y-coordinates are stored alternatingly? If you used

std::vector< std::pair< double, double > >

instead, the problem would just go away and you could use the iterator type
provided by std::vector.


Alternatively you would have to construct a temporary proxy object that
fakes the pair< double, double > reference you want to return. If you want
an iterator and not just a const_iterator, said proxy object would (a)
internally construct a pair<double,double> from the values in the vector,
(b) convert silently into a pair<double,double>& on demand, and (c) upon
destruction write back the possibly changed coordinates into the vector
(for this reason, the proxy also needs to remember the indices of the
original values).


Best

Kai-Uwe Bux
 
R

Roland Pibinger

Alternatively you would have to construct a temporary proxy object that
fakes the pair< double, double > reference you want to return. If you want
an iterator and not just a const_iterator, said proxy object would (a)
internally construct a pair<double,double> from the values in the vector,
(b) convert silently into a pair<double,double>& on demand, and (c) upon
destruction write back the possibly changed coordinates into the vector
(for this reason, the proxy also needs to remember the indices of the
original values).

A member in Polygon::iterator would be easier:

// not tested
class Polygon{
class iterator {
pair<double, double> current;
public:
pointer operator->() const {
current = pair<double,double>(*_points, *(_points+1));
return &current;
}
// ...
};
};
 
K

Kai-Uwe Bux

Roland said:
A member in Polygon::iterator would be easier:

// not tested
class Polygon{
class iterator {
pair<double, double> current;
public:
pointer operator->() const {
current = pair<double,double>(*_points, *(_points+1));
return &current;
}
// ...
};
};

That would work for a const_iterator. I do not see, however, how that
mechanism deals with uses of iterator that would need to write to the
container, like

iter->first = 0.2;


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top